home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / unix / rcs.09 < prev    next >
Internet Message Format  |  1989-11-19  |  90KB

  1. Path: xanth!mcnc!rutgers!sun-barr!newstop!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i224:  rcs - revision control system, Part09/14
  5. Message-ID: <128100@sun.Eng.Sun.COM>
  6. Date: 19 Nov 89 09:25:27 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 3216
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
  12. Posting-number: Volume 89, Issue 224
  13. Archive-name: unix/rcs.09
  14.  
  15. # This is a shell archive.
  16. # Remove anything above and including the cut line.
  17. # Then run the rest of the file through 'sh'.
  18. # Unpacked files will be owned by you and have default permissions.
  19. #----cut here-----cut here-----cut here-----cut here----#
  20. #!/bin/sh
  21. # shar: SHell ARchive
  22. # Run the following text through 'sh' to create:
  23. #    rcs/rcs.rcsfiles/rcsclean.sh,v
  24. #    rcs/rcs.rcsfiles/rcsedit.c,v
  25. #    rcs/rcs.rcsfiles/rcsfcmp.c,v
  26. #    rcs/rcs.rcsfiles/rcsfnms.c,v
  27. # This is archive 9 of a 14-part kit.
  28. # This archive created: Sun Nov 19 01:12:10 1989
  29. if `test ! -d rcs`
  30. then
  31.   mkdir rcs
  32.   echo "mkdir rcs"
  33. fi
  34. if `test ! -d rcs/rcs.rcsfiles`
  35. then
  36.   mkdir rcs/rcs.rcsfiles
  37.   echo "mkdir rcs/rcs.rcsfiles"
  38. fi
  39. echo "extracting rcs/rcs.rcsfiles/rcsclean.sh,v"
  40. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsclean.sh,v
  41. Xhead     1.5;
  42. Xbranch   1.5.2;
  43. Xaccess   ;
  44. Xsymbols  amiga_rcs:1.5.2 cbmvax_source:1.5.1 uunet_june89_dist:1.5;
  45. Xlocks    ; strict;
  46. Xcomment  @# @;
  47. X
  48. X
  49. X1.5
  50. Xdate     86.07.03.13.09.55;  author jdl;  state Exp;
  51. Xbranches 1.5.1.1 1.5.2.1;
  52. Xnext     ;
  53. X
  54. X1.5.1.1
  55. Xdate     89.08.11.01.42.19;  author rsbx;  state Exp;
  56. Xbranches ;
  57. Xnext     ;
  58. X
  59. X1.5.2.1
  60. Xdate     89.10.13.19.20.06;  author rsbx;  state Exp;
  61. Xbranches ;
  62. Xnext     ;
  63. X
  64. X
  65. Xdesc
  66. X@RCS cleanup operation.
  67. X@
  68. X
  69. X
  70. X
  71. X1.5
  72. Xlog
  73. X@checked in with -k by rsbx at 89.08.10.16.18.40.
  74. X@
  75. Xtext
  76. X@#! /bin/sh
  77. X#
  78. X# RCS cleanup operation.
  79. X# $Header: /arthur/src/local/bin/rcs/src/RCS/rcsclean.sh,v 1.5 86/07/03 13:09:55 jdl Exp $
  80. X#
  81. X# This program removes working files which are copies of the latest
  82. X# revision on the default branch of the corresponding RCS files.
  83. X# For each file given, rcsclean performs a co operation for the latest
  84. X# revision on the default branch, and compares
  85. X# the result with the working file. If the two are identical,
  86. X# the working file is deleted.
  87. X#
  88. X# A typical application in a Makefile would be:
  89. X# clean:;       rm *.o; rcsclean *.c *.o
  90. X#
  91. X# Limitation: This program doesn't work if given the name of
  92. X# an RCS file rather than the name of the working file.
  93. X
  94. XPATH=/usr/new/bin:/usr/local/bin:/bin:/usr/bin:/usr/ucb
  95. Xexport PATH
  96. Xprogname=$0
  97. Xif [ $# = 0 ] ; then
  98. X    echo        "usage: $progname file ..."
  99. X    echo        "removes all working files that are checked in and are unchanged"
  100. X    exit  0
  101. Xfi
  102. XTMPFILE=/tmp/rcscl$$.tmp
  103. Xwhile test $# -gt 0 ; do
  104. X    if test -f $1 ; then
  105. X    co -p -q $1 > $TMPFILE
  106. X    if [ $? = 0 ] ; then
  107. X        cmp -s $1 $TMPFILE
  108. X        if [ $? = 0 ] ; then
  109. X        chmod +w $1; rm -f $1; rcs -u -q $1
  110. X        fi
  111. X    fi
  112. X    fi
  113. X    shift
  114. Xdone
  115. Xrm -f $TMPFILE
  116. X@
  117. X
  118. X
  119. X1.5.2.1
  120. Xlog
  121. X@Start of Amiga RCS port branch.
  122. X@
  123. Xtext
  124. X@d4 1
  125. Xa4 1
  126. X# $Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/rcsclean.sh,v 1.5.1.1 89/08/11 01:42:19 rsbx Exp Locker: rsbx $
  127. X@
  128. X
  129. X
  130. X1.5.1.1
  131. Xlog
  132. X@Start of cbmvax RCS source branch.
  133. X@
  134. Xtext
  135. X@d4 1
  136. Xa4 1
  137. X# $Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/rcsclean.sh,v 1.5 86/07/03 13:09:55 jdl Exp $
  138. X@
  139. SHAR_EOF
  140. echo "extracting rcs/rcs.rcsfiles/rcsedit.c,v"
  141. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsedit.c,v
  142. Xhead     4.8;
  143. Xbranch   4.8.2;
  144. Xaccess   ;
  145. Xsymbols  amiga_rcs:4.8.2 cbmvax_source:4.8.1 uunet_june89_dist:4.8;
  146. Xlocks    ; strict;
  147. Xcomment  @ * @;
  148. X
  149. X
  150. X4.8
  151. Xdate     89.05.01.15.12.35;  author narten;  state Exp;
  152. Xbranches 4.8.1.1 4.8.2.1;
  153. Xnext     ;
  154. X
  155. X4.8.1.1
  156. Xdate     89.08.11.01.42.25;  author rsbx;  state Exp;
  157. Xbranches ;
  158. Xnext     ;
  159. X
  160. X4.8.2.1
  161. Xdate     89.10.13.19.18.24;  author rsbx;  state Exp;
  162. Xbranches ;
  163. Xnext     4.8.2.2;
  164. X
  165. X4.8.2.2
  166. Xdate     89.10.15.15.44.09;  author rsbx;  state Exp;
  167. Xbranches ;
  168. Xnext     4.8.2.3;
  169. X
  170. X4.8.2.3
  171. Xdate     89.10.16.19.07.14;  author rsbx;  state Exp;
  172. Xbranches ;
  173. Xnext     4.8.2.4;
  174. X
  175. X4.8.2.4
  176. Xdate     89.10.16.23.42.40;  author rsbx;  state Exp;
  177. Xbranches ;
  178. Xnext     ;
  179. X
  180. X
  181. Xdesc
  182. X@RCS stream editor.
  183. X@
  184. X
  185. X
  186. X
  187. X4.8
  188. Xlog
  189. X@checked in with -k by rsbx at 89.08.10.16.19.26.
  190. X@
  191. Xtext
  192. X@/*
  193. X *                     RCS stream editor
  194. X */
  195. X#ifndef lint
  196. Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8 89/05/01 15:12:35 narten Exp $ Purdue CS";
  197. X#endif
  198. X/**********************************************************************************
  199. X *                       edits the input file according to a
  200. X *                       script from stdin, generated by diff -n
  201. X *                       performs keyword expansion
  202. X **********************************************************************************
  203. X */
  204. X
  205. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  206. X * All rights reserved.
  207. X *
  208. X * Redistribution and use in source and binary forms are permitted
  209. X * provided that the above copyright notice and this paragraph are
  210. X * duplicated in all such forms and that any documentation,
  211. X * advertising materials, and other materials related to such
  212. X * distribution and use acknowledge that the software was developed
  213. X * by Walter Tichy.
  214. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  215. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  216. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  217. X *
  218. X * Report all problems and direct all questions to:
  219. X *   rcs-bugs@@cs.purdue.edu
  220. X * 
  221. X
  222. X
  223. X
  224. X
  225. X
  226. X
  227. X
  228. X*/
  229. X
  230. X
  231. X/* $Log:    rcsedit.c,v $
  232. X * Revision 4.8  89/05/01  15:12:35  narten
  233. X * changed copyright header to reflect current distribution rules
  234. X * 
  235. X * Revision 4.7  88/11/08  13:54:14  narten
  236. X * misplaced semicolon caused infinite loop
  237. X * 
  238. X * Revision 4.6  88/11/08  12:01:41  narten
  239. X * changes from  eggert@@sm.unisys.com (Paul Eggert)
  240. X * 
  241. X * Revision 4.6  88/08/09  19:12:45  eggert
  242. X * Shrink stdio code size; allow cc -R.
  243. X * 
  244. X * Revision 4.5  87/12/18  11:38:46  narten
  245. X * Changes from the 43. version. Don't know the significance of the
  246. X * first change involving "rewind". Also, additional "lint" cleanup.
  247. X * (Guy Harris)
  248. X * 
  249. X * Revision 4.4  87/10/18  10:32:21  narten
  250. X * Updating version numbers. Changes relative to version 1.1 actually
  251. X * relative to 4.1
  252. X * 
  253. X * Revision 1.4  87/09/24  13:59:29  narten
  254. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  255. X * warnings)
  256. X * 
  257. X * Revision 1.3  87/09/15  16:39:39  shepler
  258. X * added an initializatin of the variables editline and linecorr
  259. X * this will be done each time a file is processed.
  260. X * (there was an obscure bug where if co was used to retrieve multiple files
  261. X *  it would dump)
  262. X * fix attributed to  Roy Morris @@FileNet Corp ...!felix!roy
  263. X * 
  264. X * Revision 1.2  87/03/27  14:22:17  jenkins
  265. X * Port to suns
  266. X * 
  267. X * Revision 1.1  84/01/23  14:50:20  kcs
  268. X * Initial revision
  269. X * 
  270. X * Revision 4.1  83/05/12  13:10:30  wft
  271. X * Added new markers Id and RCSfile; added locker to Header and Id.
  272. X * Overhauled expandline completely() (problem with $01234567890123456789@@).
  273. X * Moved trymatch() and marker table to rcskeys.c.
  274. X * 
  275. X * Revision 3.7  83/05/12  13:04:39  wft
  276. X * Added retry to expandline to resume after failed match which ended in $.
  277. X * Fixed truncation problem for $19chars followed by@@@@.
  278. X * Log no longer expands full path of RCS file.
  279. X * 
  280. X * Revision 3.6  83/05/11  16:06:30  wft
  281. X * added retry to expandline to resume after failed match which ended in $.
  282. X * Fixed truncation problem for $19chars followed by@@@@.
  283. X * 
  284. X * Revision 3.5  82/12/04  13:20:56  wft
  285. X * Added expansion of keyword Locker.
  286. X *
  287. X * Revision 3.4  82/12/03  12:26:54  wft
  288. X * Added line number correction in case editing does not start at the
  289. X * beginning of the file.
  290. X * Changed keyword expansion to always print a space before closing KDELIM;
  291. X * Expansion for Header shortened.
  292. X *
  293. X * Revision 3.3  82/11/14  14:49:30  wft
  294. X * removed Suffix from keyword expansion. Replaced fclose with ffclose.
  295. X * keyreplace() gets log message from delta, not from curlogmsg.
  296. X * fixed expression overflow in while(c=putc(GETC....
  297. X * checked nil printing.
  298. X *
  299. X * Revision 3.2  82/10/18  21:13:39  wft
  300. X * I added checks for write errors during the co process, and renamed
  301. X * expandstring() to xpandstring().
  302. X *
  303. X * Revision 3.1  82/10/13  15:52:55  wft
  304. X * changed type of result of getc() from char to int.
  305. X * made keyword expansion loop in expandline() portable to machines
  306. X * without sign-extension.
  307. X */
  308. X
  309. X
  310. X#include "rcsbase.h"
  311. X
  312. X
  313. Xextern FILE * fopen();
  314. Xextern char * mktempfile();
  315. Xextern char * bindex();
  316. Xextern FILE * finptr, * frewrite;
  317. Xextern int rewriteflag;
  318. Xextern int nextc;
  319. Xextern char * RCSfilename, * workfilename;
  320. Xextern char * bindex();
  321. Xextern char * getfullRCSname();
  322. Xextern enum markers trymatch();
  323. X
  324. X
  325. XFILE  * fcopy,  * fedit; /* result and edit file descriptors                */
  326. Xchar  *resultfile;       /* result file name                                */
  327. Xchar  * editfile;        /* edit   file name                                */
  328. Xint editline;  /*line counter in fedit; starts with 1, is always #lines+1   */
  329. Xint linecorr;  /*contains #adds - #deletes in each edit run.                */
  330. X               /*used to correct editline in case file is not rewound after */
  331. X               /* applying one delta                                        */
  332. X
  333. Xiniteditfiles(dir)
  334. Xchar * dir;
  335. X/* Function: Initializes resultfile and editfile with temporary filenames
  336. X * in directory dir. Opens resultfile for reading and writing, with fcopy
  337. X * as file descriptor. fedit is set to nil.
  338. X */
  339. X{
  340. X    editline = linecorr = 0;    /* make sure we start from the beginning*/
  341. X        resultfile=mktempfile(dir,TMPFILE1);
  342. X        editfile  =mktempfile(dir,TMPFILE2);
  343. X        fedit=nil;
  344. X        if ((fcopy=fopen(resultfile,"w+"))==NULL) {
  345. X                faterror("Can't open working file %s",resultfile);
  346. X        }
  347. X}
  348. X
  349. X
  350. Xswapeditfiles(tostdout)
  351. X/* Function: swaps resultfile and editfile, assigns fedit=fcopy,
  352. X * rewinds fedit for reading, and opens resultfile for reading and
  353. X * writing, using fcopy. If tostdout, fcopy is set to stdout.
  354. X */
  355. X{       char * tmpptr;
  356. X        if(ferror(fcopy))
  357. X                faterror("write failed on %s -- file system full?",resultfile);
  358. X        fedit=fcopy;
  359. X        rewind(fedit);
  360. X        editline = 1; linecorr=0;
  361. X        tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
  362. X        if (tostdout)
  363. X                fcopy=stdout;
  364. X        elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
  365. X                faterror("Can't open working file %s",resultfile);
  366. X        }
  367. X}
  368. X
  369. X
  370. Xfinishedit(delta)
  371. Xstruct hshentry * delta;
  372. X/* copy the rest of the edit file and close it (if it exists).
  373. X * if delta!=nil, perform keyword substitution at the same time.
  374. X */
  375. X{
  376. X        register int c;
  377. X        if (fedit!=nil) {
  378. X                if (delta!=nil) {
  379. X                        while (expandline(fedit,fcopy,delta,false,false)) editline++;
  380. X                } else {
  381. X                        while((c=getc(fedit))!=EOF) {
  382. X                                VOID putc(c,fcopy);
  383. X                                if (c=='\n') editline++;
  384. X                        }
  385. X                }
  386. X                ffclose(fedit);
  387. X        }
  388. X}
  389. X
  390. X
  391. Xcopylines(line,delta)
  392. Xregister int line; struct hshentry * delta;
  393. X/* Function: copies input lines editline..line-1 from fedit to fcopy.
  394. X * If delta != nil, keyword expansion is done simultaneously.
  395. X * editline is updated. Rewinds a file only if necessary.
  396. X */
  397. X{
  398. X
  399. X        if (editline>line) {
  400. X                /* swap files */
  401. X                finishedit((struct hshentry *)nil); swapeditfiles(false);
  402. X                /* assumes edit only during last pass, from the beginning*/
  403. X        }
  404. X        while (editline<line) {
  405. X                /*copy another line*/
  406. X                if (delta)
  407. X                        VOID expandline(fedit,fcopy,delta,false,false);
  408. X                else
  409. X                        while (putc(getc(fedit),fcopy)!='\n');
  410. X                editline++;
  411. X        }
  412. X}
  413. X
  414. X
  415. X
  416. Xxpandstring(delta)
  417. Xstruct hshentry * delta;
  418. X/* Function: Reads a string terminated by SDELIM from finptr and writes it
  419. X * to fcopy. Double SDELIM is replaced with single SDELIM.
  420. X * Keyword expansion is performed with data from delta.
  421. X * If rewriteflag==true, the string is also copied unchanged to frewrite.
  422. X * editline is updated.
  423. X */
  424. X{
  425. X        editline=1;
  426. X        while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
  427. X        nextc='\n';
  428. X}
  429. X
  430. X
  431. Xcopystring()
  432. X/* Function: copies a string terminated with a single SDELIM from finptr to
  433. X * fcopy, replacing all double SDELIM with a single SDELIM.
  434. X * If rewriteflag==true, the string also copied unchanged to frewrite.
  435. X * editline is set to (number of lines copied)+1.
  436. X * Assumption: next character read is first string character.
  437. X */
  438. X{    register c;
  439. X    register FILE *fin, *frew, *fcop;
  440. X    register write;
  441. X
  442. X    fin=finptr; frew=frewrite; fcop=fcopy;
  443. X        write=rewriteflag;
  444. X        editline=1;
  445. X        while ((c=GETC(fin,frew,write)) != EOF) {
  446. X                if ((c==SDELIM)&&((c=GETC(fin,frew,write)) != SDELIM)){
  447. X                        /* end of string */
  448. X                        nextc = c;
  449. X                        return;
  450. X                }
  451. X                VOID putc(c,fcop);
  452. X                if (c=='\n') editline++;
  453. X        }
  454. X        nextc = c;
  455. X        serror("Unterminated string");
  456. X        return;
  457. X}
  458. X
  459. X
  460. X
  461. X
  462. Xeditstring(delta)
  463. Xstruct hshentry * delta;
  464. X/* Function: reads an edit script from finptr and applies it to
  465. X * file fedit; the result is written to fcopy.
  466. X * If delta!=nil, keyword expansion is performed simultaneously.
  467. X * If frewrite==true, the edit script is also copied verbatim to frewrite.
  468. X * Assumes that all these files are open.
  469. X * If running out of lines in fedit, fedit and fcopy are swapped.
  470. X * resultfile and editfile are the names of the files that go with fcopy
  471. X * and fedit, respectively.
  472. X * Assumes the next input character from finptr is the first character of
  473. X * the edit script. Resets nextc on exit.
  474. X */
  475. X{
  476. X        int ed; /* editor command */
  477. X        register int c;
  478. X    register FILE *fin, *frew;
  479. X        register int write, i;
  480. X        int line, length;
  481. X
  482. X    fin=finptr;  frew=frewrite;
  483. X        editline += linecorr; linecorr=0; /*correct line number*/
  484. X        write=rewriteflag;
  485. X        for (;;) {
  486. X                /* read next command and decode */
  487. X                /* assume next non-white character is command name*/
  488. X                while((ed=GETC(fin,frew,write))=='\n'||
  489. X                        ed==' ' || ed=='\t');
  490. X                if (ed==SDELIM) break;
  491. X                /* now attempt to read numbers. */
  492. X                /* fscanf causes trouble because of the required echoing */
  493. X                while ((c=GETC(fin,frew,write))==' ');  /*skip spaces*/
  494. X                if (!('0'<=c && c<='9')) {
  495. X                        faterror("missing line number in edit script");
  496. X                        break;
  497. X                }
  498. X                line= c -'0';
  499. X                while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
  500. X                        line = line*10 + c-'0';
  501. X                }
  502. X                while (c==' ') c=GETC(fin,frew,write);
  503. X                if (!('0'<=c && c<='9')) {
  504. X                        faterror("incorrect range in edit script");
  505. X                        break;
  506. X                }
  507. X                length= c -'0';
  508. X                while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
  509. X                        length = length*10 + c-'0';
  510. X                }
  511. X                while(c!='\n'&&c!=EOF) c=GETC(fin,frew,write); /* skip to end of line */
  512. X
  513. X                switch (ed) {
  514. X                case 'd':
  515. X                        copylines(line,delta);
  516. X                        /* skip over unwanted lines */
  517. X                        for (i=length;i>0;i--) {
  518. X                                /*skip next line*/
  519. X                                while ((c=getc(fedit))!='\n')
  520. X                    if (c==EOF)
  521. X                        faterror("EOF during edit");
  522. X                                editline++;
  523. X                        }
  524. X                        linecorr -= length;
  525. X                        break;
  526. X                case 'a':
  527. X                        copylines(line+1,delta); /*copy only; no delete*/
  528. X                        for (i=length;i>0;i--) {
  529. X                                /*copy next line from script*/
  530. X                                if (delta!=nil)
  531. X                                       VOID expandline(fin,fcopy,delta,true,write);
  532. X                                else {
  533. X                                       c = GETC(fin,frew,write);
  534. X                                       while (putc(c,fcopy)!='\n'){
  535. X                                               if ((c==SDELIM)&&((c=GETC(fin,frew,write))!=SDELIM)){
  536. X                                                       serror("Missing string delimiter in edit script");
  537. X                                                       VOID putc(c,fcopy);
  538. X                                               }
  539. X                                               c = GETC(fin,frew,write);
  540. X                                       }
  541. X                                }
  542. X                        }
  543. X                        linecorr += length;
  544. X                        break;
  545. X                default:
  546. X                        faterror("unknown command in edit script: %c", ed);
  547. X                        break;
  548. X                }
  549. X        }
  550. X        nextc=GETC(fin,frew,write);
  551. X}
  552. X
  553. X
  554. X
  555. X/* The rest is for keyword expansion */
  556. X
  557. X
  558. X
  559. Xexpandline(in, out, delta,delimstuffed,write)
  560. Xregister FILE * in, * out; struct hshentry * delta;
  561. Xint delimstuffed, write;
  562. X/* Function: Reads a line from in and writes it to out.
  563. X * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
  564. X * Keyword expansion is performed with data from delta.
  565. X * If write==true, the string is also copied unchanged to frewrite.
  566. X * Returns false if end-of-string or end-of-line is detected, true otherwise.
  567. X */
  568. X{
  569. X    register c;
  570. X    register FILE * frew;
  571. X    register w, ds;
  572. X    register char * tp;
  573. X    char keystring[keylength+2];
  574. X    char keyval[keyvallength+2];
  575. X        enum markers matchresult;
  576. X
  577. X    frew = frewrite;
  578. X    w = write;
  579. X    ds = delimstuffed;
  580. X    c=GETC(in,frew,w);
  581. X        for (;;) {
  582. X                if (c==EOF) {
  583. X                        if(ds) {
  584. X                                error("unterminated string");
  585. X                                nextc=c;
  586. X                        }
  587. X                        return(false);
  588. X                }
  589. X
  590. X                if (c==SDELIM && ds) {
  591. X                        if ((c=GETC(in,frew,w))!=SDELIM) {
  592. X                                /* end of string */
  593. X                                nextc=c;
  594. X                                return false;
  595. X                        }
  596. X                }
  597. X                VOID putc(c,out);
  598. X
  599. X                if (c=='\n') return true; /* end of line */
  600. X
  601. X        if (c==KDELIM) {
  602. X                        /* check for keyword */
  603. X                        /* first, copy a long enough string into keystring */
  604. X            tp=keystring;
  605. X            while (((c=GETC(in,frew,w))!=EOF) && (tp<keystring+keylength) && (c!='\n')
  606. X                   && (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
  607. X                              VOID putc(c,out);
  608. X                  *tp++ = c;
  609. X                        }
  610. X            *tp++ = c; *tp = '\0';
  611. X            matchresult=trymatch(keystring,false);
  612. X            if (matchresult==Nomatch) continue;
  613. X            /* last c will be dealt with properly by continue*/
  614. X
  615. X            /* Now we have a keyword terminated with a K/VDELIM */
  616. X            if (c==VDELIM) {
  617. X                  /* try to find closing KDELIM, and replace value */
  618. X                  tp=keyval;
  619. X                  while (((c=GETC(in,frew,w)) != EOF)
  620. X                     && (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
  621. X                      *tp++ =c;
  622. X                      if (c==SDELIM && ds) { /*skip next SDELIM */
  623. X                        c=GETC(in,frew,w);
  624. X                        /* Can't be at end of string.
  625. X                        /* always a \n before closing SDELIM */
  626. X                      }
  627. X                  }
  628. X                  if (c!=KDELIM) {
  629. X                    /* couldn't find closing KDELIM -- give up */
  630. X                    VOID putc(VDELIM,out); *tp='\0';
  631. X                    VOID fputs(keyval,out);
  632. X                    continue;   /* last c handled properly */
  633. X                  }
  634. X            }
  635. X            /* now put out the new keyword value */
  636. X            keyreplace(matchresult,delta,out);
  637. X                }
  638. X                c=GETC(in,frew,w);
  639. X        } /* end for */
  640. X}
  641. X
  642. X
  643. X
  644. Xkeyreplace(marker,delta,out)
  645. Xenum markers marker; struct hshentry * delta; register FILE * out;
  646. X/* function: ouputs the keyword value(s) corresponding to marker.
  647. X * Attributes are derived from delta.
  648. X */
  649. X{
  650. X        char * date;
  651. X        register char * sp;
  652. X
  653. X        date= delta->date;
  654. X
  655. X        switch (marker) {
  656. X        case Author:
  657. X                VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
  658. X                break;
  659. X        case Date:
  660. X                VOID putc(VDELIM,out);VOID putc(' ',out);
  661. X                VOID PRINTDATE(out,date);VOID putc(' ',out);
  662. X                VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
  663. X                break;
  664. X        case Id:
  665. X    case Header:
  666. X        VOID putc(VDELIM,out); VOID putc(' ',out);
  667. X        if (marker==Id)
  668. X             VOID fputs(bindex(RCSfilename,'/'),out);
  669. X        else     VOID fputs(getfullRCSname(),out);
  670. X        VOID fprintf(out," %s ", delta->num);
  671. X                VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
  672. X        VOID fprintf(out, " %s %s ",delta->author,delta->state);
  673. X        if (delta->lockedby!=nil)
  674. X             VOID fprintf(out,"Locker: %s ",delta->lockedby);
  675. X        VOID putc(KDELIM,out);
  676. X                break;
  677. X        case Locker:
  678. X                VOID fprintf(out,"%c %s %c", VDELIM,
  679. X                        delta->lockedby==nil?"":delta->lockedby,KDELIM);
  680. X                break;
  681. X        case Log:
  682. X                VOID fprintf(out, "%c\t%s %c\n%sRevision %s  ",
  683. X                        VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
  684. X                VOID PRINTDATE(out,date);VOID fputs("  ",out);VOID PRINTTIME(out,date);
  685. X                VOID fprintf(out, "  %s\n%s",delta->author,Comment);
  686. X                /* do not include state here because it may change and is not updated*/
  687. X                sp = delta->log;
  688. X                while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
  689. X                /* Comment is the comment leader */
  690. X                break;
  691. X        case RCSfile:
  692. X                VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
  693. X                break;
  694. X        case Revision:
  695. X                VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
  696. X                break;
  697. X        case Source:
  698. X                VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
  699. X                break;
  700. X        case State:
  701. X                VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
  702. X                break;
  703. X        case Nomatch:
  704. X                VOID putc(KDELIM,out);
  705. X                break;
  706. X        }
  707. X}
  708. X
  709. X
  710. X@
  711. X
  712. X
  713. X4.8.2.1
  714. Xlog
  715. X@Start of Amiga RCS port branch.
  716. X@
  717. Xtext
  718. X@d5 1
  719. Xa5 5
  720. X<<<<<<< rcsedit.c
  721. Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.1.1 89/08/11 01:42:25 rsbx Exp Locker: rsbx $ Purdue CS";
  722. X=======
  723. Xstatic char rcsid[]= "$Id: rcsedit.c,v 1.2 89/09/17 13:35:29 rick Exp $ Purdue CS";
  724. X>>>>>>> 1.2
  725. Xa40 11
  726. X<<<<<<< rcsedit.c
  727. X * Revision 4.8.1.1  89/08/11  01:42:25  rsbx
  728. X * Start of cbmvax RCS source branch.
  729. X=======
  730. X * Revision 1.2  89/09/17  13:35:29  rick
  731. X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
  732. X * All changes done with conditional compile (#ifdef AMIGA).  This version
  733. X * compiles correctly with Lattice C version 5.02 or later.
  734. X>>>>>>> 1.2
  735. X * 
  736. X<<<<<<< rcsedit.c
  737. Xa41 3
  738. X * checked in with -k by rsbx at 89.08.10.16.19.26.
  739. X * 
  740. X * Revision 4.8  89/05/01  15:12:35  narten
  741. Xa52 5
  742. X=======
  743. X * Revision 1.2  88/09/03  15:09:56  rick
  744. X * Port to AmigaDos.  All done with conditional compiles
  745. X * 
  746. X>>>>>>> 1.2
  747. Xa166 2
  748. X        if (fedit != NULL)
  749. X            fclose(fedit);
  750. X@
  751. X
  752. X
  753. X4.8.2.2
  754. Xlog
  755. X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  756. Xsources I have here (and are later than the ones Rick used).
  757. X@
  758. Xtext
  759. X@d5 5
  760. Xa9 1
  761. Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.1 89/10/13 19:18:24 rsbx Exp Locker: rsbx $ Purdue CS";
  762. Xd45 1
  763. Xa45 3
  764. X * Revision 4.8.2.1  89/10/13  19:18:24  rsbx
  765. X * Start of Amiga RCS port branch.
  766. X * 
  767. Xd48 6
  768. Xd55 1
  769. Xd71 5
  770. Xd457 1
  771. Xa457 1
  772. X                        GETC(in,frew,w);
  773. X@
  774. X
  775. X
  776. X4.8.2.3
  777. Xlog
  778. X@Changed file path handling to deal with Amiga file path sematics.
  779. X@
  780. Xtext
  781. X@d5 1
  782. Xa5 1
  783. Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.2 89/10/15 15:44:09 rsbx Exp $ Purdue CS";
  784. Xa40 4
  785. X * Revision 4.8.2.2  89/10/15  15:44:09  rsbx
  786. X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  787. X * sources I have here (and are later than the ones Rick used).
  788. X * 
  789. Xd133 1
  790. Xd138 1
  791. Xd488 1
  792. Xa488 1
  793. X             VOID fputs(fnamepart(RCSfilename),out);
  794. Xd503 1
  795. Xa503 1
  796. X                        VDELIM, fnamepart(RCSfilename), KDELIM, Comment, delta->num);
  797. Xd512 1
  798. Xa512 1
  799. X                VOID fprintf(out,"%c %s %c",VDELIM,fnamepart(RCSfilename),KDELIM);
  800. X@
  801. X
  802. X
  803. X4.8.2.4
  804. Xlog
  805. X@Added function return type for fnamepart().
  806. X@
  807. Xtext
  808. X@d5 1
  809. Xa5 1
  810. Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.3 89/10/16 19:07:14 rsbx Exp $ Purdue CS";
  811. Xa40 3
  812. X * Revision 4.8.2.3  89/10/16  19:07:14  rsbx
  813. X * Changed file path handling to deal with Amiga file path sematics.
  814. X * 
  815. Xa135 1
  816. Xextern char * fnamepart();
  817. X@
  818. X
  819. X
  820. X4.8.1.1
  821. Xlog
  822. X@Start of cbmvax RCS source branch.
  823. X@
  824. Xtext
  825. X@a41 3
  826. X * checked in with -k by rsbx at 89.08.10.16.19.26.
  827. X * 
  828. X * Revision 4.8  89/05/01  15:12:35  narten
  829. X@
  830. SHAR_EOF
  831. echo "extracting rcs/rcs.rcsfiles/rcsfcmp.c,v"
  832. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfcmp.c,v
  833. Xhead     4.5;
  834. Xbranch   4.5.2;
  835. Xaccess   ;
  836. Xsymbols  amiga_rcs:4.5.2 cbmvax_source:4.5.1 uunet_june89_dist:4.5;
  837. Xlocks    ; strict;
  838. Xcomment  @ * @;
  839. X
  840. X
  841. X4.5
  842. Xdate     89.05.01.15.12.42;  author narten;  state Exp;
  843. Xbranches 4.5.1.1 4.5.2.1;
  844. Xnext     ;
  845. X
  846. X4.5.1.1
  847. Xdate     89.08.11.01.42.29;  author rsbx;  state Exp;
  848. Xbranches ;
  849. Xnext     ;
  850. X
  851. X4.5.2.1
  852. Xdate     89.10.13.19.18.28;  author rsbx;  state Exp;
  853. Xbranches ;
  854. Xnext     4.5.2.2;
  855. X
  856. X4.5.2.2
  857. Xdate     89.10.15.15.44.13;  author rsbx;  state Exp;
  858. Xbranches ;
  859. Xnext     ;
  860. X
  861. X
  862. Xdesc
  863. X@RCS file comparison.
  864. X@
  865. X
  866. X
  867. X
  868. X4.5
  869. Xlog
  870. X@checked in with -k by rsbx at 89.08.10.16.19.42.
  871. X@
  872. Xtext
  873. X@/*
  874. X *                     RCS file comparison
  875. X */
  876. X#ifndef lint
  877. Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5 89/05/01 15:12:42 narten Exp $ Purdue CS";
  878. X#endif
  879. X/*****************************************************************************
  880. X *                       rcsfcmp()
  881. X *                       Testprogram: define FCMPTEST
  882. X *****************************************************************************
  883. X */
  884. X
  885. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  886. X * All rights reserved.
  887. X *
  888. X * Redistribution and use in source and binary forms are permitted
  889. X * provided that the above copyright notice and this paragraph are
  890. X * duplicated in all such forms and that any documentation,
  891. X * advertising materials, and other materials related to such
  892. X * distribution and use acknowledge that the software was developed
  893. X * by Walter Tichy.
  894. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  895. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  896. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  897. X *
  898. X * Report all problems and direct all questions to:
  899. X *   rcs-bugs@@cs.purdue.edu
  900. X * 
  901. X
  902. X
  903. X
  904. X
  905. X
  906. X
  907. X
  908. X*/
  909. X
  910. X
  911. X
  912. X
  913. X
  914. X/* $Log:    rcsfcmp.c,v $
  915. X * Revision 4.5  89/05/01  15:12:42  narten
  916. X * changed copyright header to reflect current distribution rules
  917. X * 
  918. X * Revision 4.4  88/11/08  12:01:33  narten
  919. X * changes from  eggert@@sm.unisys.com (Paul Eggert)
  920. X * 
  921. X * Revision 4.4  88/08/09  19:12:50  eggert
  922. X * Shrink stdio code size.
  923. X * 
  924. X * Revision 4.3  87/12/18  11:40:02  narten
  925. X * lint cleanups (Guy Harris)
  926. X * 
  927. X * Revision 4.2  87/10/18  10:33:06  narten
  928. X * updting version number. Changes relative to 1.1 actually relative to 
  929. X * 4.1
  930. X * 
  931. X * Revision 1.2  87/03/27  14:22:19  jenkins
  932. X * Port to suns
  933. X * 
  934. X * Revision 1.1  84/01/23  14:50:23  kcs
  935. X * Initial revision
  936. X * 
  937. X * Revision 4.1  83/05/10  16:24:04  wft
  938. X * Marker matching now uses trymatch(). Marker pattern is now
  939. X * checked precisely.
  940. X * 
  941. X * Revision 3.1  82/12/04  13:21:40  wft
  942. X * Initial revision.
  943. X *
  944. X */
  945. X
  946. X/*
  947. X#define FCMPTEST
  948. X/* Testprogram; prints out whether two files are identical,
  949. X * except for keywords
  950. X */
  951. X
  952. X#include  "rcsbase.h"
  953. Xextern FILE * fopen();
  954. Xextern enum markers trymatch(); /* check for keywords */
  955. X
  956. X
  957. Xrcsfcmp(xfname,uxfname,delta)
  958. Xchar * xfname, *uxfname; struct hshentry *delta;
  959. X/* Function: compares the files xfname and uxfname. Returns true
  960. X * if xfname has the same contents as uxfname, while disregarding
  961. X * keyword values. For the LOG-keyword, rcsfcmp skips the log message
  962. X * given by the parameter delta in xfname. Thus, rcsfcmp returns true
  963. X * if xfname contains the same as uxfname, with the keywords expanded.
  964. X * Implementation: character-by-character comparison until $ is found.
  965. X * If a $ is found, read in the marker keywords; if they are real keywords
  966. X * and identical, read in keyword value. If value is terminated properly,
  967. X * disregard it and optionally skip log message; otherwise, compare value.
  968. X */
  969. X{
  970. X    register int xc,uxc;
  971. X    char xkeyword[keylength+2],   uxkeyword[keylength+2];
  972. X    char xkeyval[keyvallength+1], uxkeyval[keyvallength+1];
  973. X    register FILE * xfp, * uxfp;
  974. X    register char * tp;
  975. X    int result;
  976. X    enum markers match1,match2;
  977. X
  978. X    if ((xfp=fopen(tp=xfname,"r"))==NULL || (uxfp=fopen(tp=uxfname,"r"))==NULL) {
  979. X       faterror("Can't open %s\n", tp);
  980. X       return false;
  981. X    }
  982. X    result=false;
  983. X    xc=getc(xfp); uxc=getc(uxfp);
  984. X    while( xc == uxc) { /* comparison loop */
  985. X        if (xc==EOF) { /* finished; everything is the same*/
  986. X            result=true;
  987. X            break;
  988. X        }
  989. X        if ( xc!=KDELIM) {
  990. X            /* get the next characters */
  991. X            xc=getc(xfp); uxc=getc(uxfp);
  992. X        } else {
  993. X            /* try to get both keywords */
  994. X            tp = xkeyword;
  995. X            while( (xc=getc(xfp))!=EOF && (tp< xkeyword+keylength) && (xc!='\n')
  996. X                   && (xc!=KDELIM) && (xc!=VDELIM))
  997. X                *tp++ = xc;
  998. X        *tp++ = xc;  /* add closing K/VDELIM */
  999. X            *tp='\0';
  1000. X            tp = uxkeyword;
  1001. X            while( (uxc=getc(uxfp))!=EOF && (tp< uxkeyword+keylength) && (uxc!='\n')
  1002. X                   && (uxc!=KDELIM) && (uxc!=VDELIM))
  1003. X                *tp++ = uxc;
  1004. X        *tp++ = xc;  /* add closing K/VDELIM */
  1005. X            *tp='\0';
  1006. X            /* now we have 2 keywords, or something thal looks like it.*/
  1007. X        match1=trymatch(xkeyword,false);
  1008. X        match2=trymatch(uxkeyword,false);
  1009. X        if (match1 != match2) break; /* not identical */
  1010. X#ifdef FCMPTEST
  1011. X        VOID printf("found potential keywords %s and %s\n",xkeyword,uxkeyword);
  1012. X#endif
  1013. X
  1014. X        if (match1 == Nomatch) {
  1015. X        /* not a keyword pattern, but could still be identical */
  1016. X        if (strcmp(xkeyword,uxkeyword)==0)
  1017. X             continue;
  1018. X        else break;
  1019. X        }
  1020. X#ifdef FCMPTEST
  1021. X        VOID printf("found common keyword %s\n",xkeyword);
  1022. X#endif
  1023. X        tp=xkeyval;
  1024. X        if (xc==VDELIM) {/* get value */
  1025. X        while (((xc=getc(xfp))!=KDELIM) && (xc!='\n') && (xc!=EOF) &&
  1026. X            (tp<xkeyval+keyvallength))
  1027. X            *tp++ = xc;
  1028. X        }
  1029. X        *tp = '\0';   /*xkeyval now filled with value; possibly empty*/
  1030. X        tp=uxkeyval;
  1031. X        if (uxc==VDELIM) {/* get value */
  1032. X        while (((uxc=getc(uxfp))!=KDELIM) && (uxc!='\n') && (uxc!=EOF) &&
  1033. X            (tp<uxkeyval+keyvallength))
  1034. X            *tp++ = uxc;
  1035. X        }
  1036. X        *tp = '\0';   /*uxkeyval now filled with value; possibly empty*/
  1037. X        if (xc!=uxc) break; /* not the same */
  1038. X        if (xc==KDELIM) {
  1039. X        xc=getc(xfp); uxc=getc(uxfp); /* skip closing KDELIM */
  1040. X        /* if the keyword is LOG, also skip the log message in xfp*/
  1041. X        if (match1==Log) {
  1042. X            /* first, compute the number of line feeds in log msg */
  1043. X            int lncnt, ccnt;
  1044. X            lncnt=2; tp=delta->log;
  1045. X            while(*tp) if(*tp++=='\n') lncnt++;
  1046. X            while(xc!=EOF) {
  1047. X            if (xc=='\n')
  1048. X                if(--lncnt==0) break;
  1049. X            xc=getc(xfp);
  1050. X            }
  1051. X            /* skip last comment leader */
  1052. X            /* Can't just skip another line here, because there may be */
  1053. X            /* additional characters on the line (after the Log....$)  */
  1054. X            for (ccnt=strlen(Comment); ccnt>=0; lncnt--) {
  1055. X            xc=getc(xfp);
  1056. X            if(xc=='\n') break;
  1057. X            /* reads to the end of the comment leader or '\n',     */
  1058. X            /* whatever comes first. This is because some editors  */
  1059. X            /* strip off trailing blanks from a leader like " * ". */
  1060. X            }
  1061. X        }
  1062. X        } else {
  1063. X        /* both end in the same character, but not a KDELIM */
  1064. X        /* must compare string values.*/
  1065. X#ifdef FCMPTEST
  1066. X        VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
  1067. X#endif
  1068. X        if (strcmp(xkeyval,uxkeyval)!=0) break; /*different */
  1069. X        xc=getc(xfp); uxc=getc(uxfp); /* skip closing char  */
  1070. X            }
  1071. X        }
  1072. X    }
  1073. X    VOID fclose(xfp); VOID fclose(uxfp);
  1074. X    return result;
  1075. X}
  1076. X
  1077. X
  1078. X
  1079. X#ifdef FCMPTEST
  1080. Xchar * RCSfilename, * workfilename;
  1081. X
  1082. Xchar * Comment;
  1083. X
  1084. Xmain(argc, argv)
  1085. Xint  argc; char  *argv[];
  1086. X/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
  1087. X * 4th: unexpanded file
  1088. X */
  1089. X{       struct hshentry delta;
  1090. X
  1091. X        cmdid="rcsfcmp";
  1092. X        Comment=argv[1];
  1093. X        delta.log=argv[2];
  1094. X        if (rcsfcmp(argv[3],argv[4],&delta))
  1095. X                VOID printf("files are the same\n");
  1096. X        else    VOID printf("files are different\n");
  1097. X}
  1098. X#endif
  1099. X@
  1100. X
  1101. X
  1102. X4.5.2.1
  1103. Xlog
  1104. X@Start of Amiga RCS port branch.
  1105. X@
  1106. Xtext
  1107. X@d5 1
  1108. Xa5 5
  1109. X<<<<<<< rcsfcmp.c
  1110. Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5.1.1 89/08/11 01:42:29 rsbx Exp Locker: rsbx $ Purdue CS";
  1111. X=======
  1112. Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 1.2 89/09/17 13:42:09 rick Exp $ Purdue CS";
  1113. X>>>>>>> 1.2
  1114. Xa42 16
  1115. X<<<<<<< rcsfcmp.c
  1116. X * Revision 4.5.1.1  89/08/11  01:42:29  rsbx
  1117. X * Start of cbmvax RCS source branch.
  1118. X * 
  1119. X * Revision 4.5  89/05/01  15:12:42  narten
  1120. X * checked in with -k by rsbx at 89.08.10.16.19.42.
  1121. X=======
  1122. X * Revision 1.2  89/09/17  13:42:09  rick
  1123. X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
  1124. X * All changes done with condition compile (#ifdef AMIGA).  This
  1125. X * version compiles correctly with Lattice C version 5.02 or later.
  1126. X * 
  1127. X * Revision 1.1  89/09/17  13:04:37  rick
  1128. X * Initial revision
  1129. X>>>>>>> 1.2
  1130. X * 
  1131. X@
  1132. X
  1133. X
  1134. X4.5.2.2
  1135. Xlog
  1136. X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  1137. Xsources I have here (and are later than the ones Rick used).
  1138. X@
  1139. Xtext
  1140. X@d5 5
  1141. Xa9 1
  1142. Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5.2.1 89/10/13 19:18:28 rsbx Exp Locker: rsbx $ Purdue CS";
  1143. Xd47 1
  1144. Xa47 3
  1145. X * Revision 4.5.2.1  89/10/13  19:18:28  rsbx
  1146. X * Start of Amiga RCS port branch.
  1147. X * 
  1148. Xd53 5
  1149. Xd59 4
  1150. Xd202 1
  1151. Xa202 1
  1152. X            for (ccnt=strlen(Comment); ccnt>=0;) {
  1153. X@
  1154. X
  1155. X
  1156. X4.5.1.1
  1157. Xlog
  1158. X@Start of cbmvax RCS source branch.
  1159. X@
  1160. Xtext
  1161. X@a43 3
  1162. X * checked in with -k by rsbx at 89.08.10.16.19.42.
  1163. X * 
  1164. X * Revision 4.5  89/05/01  15:12:42  narten
  1165. X@
  1166. SHAR_EOF
  1167. echo "extracting rcs/rcs.rcsfiles/rcsfnms.c,v"
  1168. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfnms.c,v
  1169. Xhead     4.8;
  1170. Xbranch   4.8.2;
  1171. Xaccess   ;
  1172. Xsymbols  amiga_rcs:4.8.2 cbmvax_source:4.8.1 uunet_june89_dist:4.8;
  1173. Xlocks    ; strict;
  1174. Xcomment  @ * @;
  1175. X
  1176. X
  1177. X4.8
  1178. Xdate     89.05.01.15.09.41;  author narten;  state Exp;
  1179. Xbranches 4.8.1.1 4.8.2.1;
  1180. Xnext     ;
  1181. X
  1182. X4.8.1.1
  1183. Xdate     89.08.11.01.42.32;  author rsbx;  state Exp;
  1184. Xbranches ;
  1185. Xnext     ;
  1186. X
  1187. X4.8.2.1
  1188. Xdate     89.10.13.19.18.32;  author rsbx;  state Exp;
  1189. Xbranches ;
  1190. Xnext     4.8.2.2;
  1191. X
  1192. X4.8.2.2
  1193. Xdate     89.10.15.15.44.18;  author rsbx;  state Exp;
  1194. Xbranches ;
  1195. Xnext     4.8.2.3;
  1196. X
  1197. X4.8.2.3
  1198. Xdate     89.10.15.18.27.52;  author rsbx;  state Exp;
  1199. Xbranches ;
  1200. Xnext     4.8.2.4;
  1201. X
  1202. X4.8.2.4
  1203. Xdate     89.10.16.19.07.19;  author rsbx;  state Exp;
  1204. Xbranches ;
  1205. Xnext     4.8.2.5;
  1206. X
  1207. X4.8.2.5
  1208. Xdate     89.10.16.23.54.04;  author rsbx;  state Exp;
  1209. Xbranches ;
  1210. Xnext     4.8.2.6;
  1211. X
  1212. X4.8.2.6
  1213. Xdate     89.10.17.16.17.29;  author rsbx;  state Exp;
  1214. Xbranches ;
  1215. Xnext     4.8.2.7;
  1216. X
  1217. X4.8.2.7
  1218. Xdate     89.10.17.18.38.55;  author rsbx;  state Exp;
  1219. Xbranches ;
  1220. Xnext     4.8.2.8;
  1221. X
  1222. X4.8.2.8
  1223. Xdate     89.10.30.13.44.29;  author rsbx;  state Exp;
  1224. Xbranches ;
  1225. Xnext     4.8.2.9;
  1226. X
  1227. X4.8.2.9
  1228. Xdate     89.10.30.13.53.10;  author rsbx;  state Exp;
  1229. Xbranches ;
  1230. Xnext     4.8.2.10;
  1231. X
  1232. X4.8.2.10
  1233. Xdate     89.11.01.14.43.14;  author rsbx;  state Exp;
  1234. Xbranches ;
  1235. Xnext     4.8.2.11;
  1236. X
  1237. X4.8.2.11
  1238. Xdate     89.11.05.18.03.59;  author rsbx;  state Exp;
  1239. Xbranches ;
  1240. Xnext     ;
  1241. X
  1242. X
  1243. Xdesc
  1244. X@RCS file name handling.
  1245. X@
  1246. X
  1247. X
  1248. X
  1249. X4.8
  1250. Xlog
  1251. X@checked in with -k by rsbx at 89.08.10.16.20.00.
  1252. X@
  1253. Xtext
  1254. X@/*
  1255. X *                     RCS file name handling
  1256. X */
  1257. X#ifndef lint
  1258. X static char
  1259. X rcsid[]= "$Id: rcsfnms.c,v 4.8 89/05/01 15:09:41 narten Exp $ Purdue CS";
  1260. X#endif
  1261. X/****************************************************************************
  1262. X *                     creation and deletion of semaphorefile,
  1263. X *                     creation of temporary filenames and cleanup()
  1264. X *                     pairing of RCS file names and working file names.
  1265. X *                     Testprogram: define PAIRTEST
  1266. X ****************************************************************************
  1267. X */
  1268. X
  1269. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  1270. X * All rights reserved.
  1271. X *
  1272. X * Redistribution and use in source and binary forms are permitted
  1273. X * provided that the above copyright notice and this paragraph are
  1274. X * duplicated in all such forms and that any documentation,
  1275. X * advertising materials, and other materials related to such
  1276. X * distribution and use acknowledge that the software was developed
  1277. X * by Walter Tichy.
  1278. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1279. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1280. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1281. X *
  1282. X * Report all problems and direct all questions to:
  1283. X *   rcs-bugs@@cs.purdue.edu
  1284. X * 
  1285. X
  1286. X
  1287. X
  1288. X
  1289. X
  1290. X
  1291. X
  1292. X*/
  1293. X
  1294. X
  1295. X
  1296. X
  1297. X/* $Log:    rcsfnms.c,v $
  1298. X * Revision 4.8  89/05/01  15:09:41  narten
  1299. X * changed getwd to not stat empty directories.
  1300. X * 
  1301. X * Revision 4.7  88/11/08  12:01:22  narten
  1302. X * changes from  eggert@@sm.unisys.com (Paul Eggert)
  1303. X * 
  1304. X * Revision 4.7  88/08/09  19:12:53  eggert
  1305. X * Fix troff macro comment leader bug; add Prolog; allow cc -R; remove lint.
  1306. X * 
  1307. X * Revision 4.6  87/12/18  11:40:23  narten
  1308. X * additional file types added from 4.3 BSD version, and SPARC assembler
  1309. X * comment character added. Also, more lint cleanups. (Guy Harris)
  1310. X * 
  1311. X * Revision 4.5  87/10/18  10:34:16  narten
  1312. X * Updating version numbers. Changes relative to 1.1 actually relative
  1313. X * to verion 4.3
  1314. X * 
  1315. X * Revision 1.3  87/03/27  14:22:21  jenkins
  1316. X * Port to suns
  1317. X * 
  1318. X * Revision 1.2  85/06/26  07:34:28  svb
  1319. X * Comment leader '% ' for '*.tex' files added.
  1320. X * 
  1321. X * Revision 1.1  84/01/23  14:50:24  kcs
  1322. X * Initial revision
  1323. X * 
  1324. X * Revision 4.3  83/12/15  12:26:48  wft
  1325. X * Added check for KDELIM in file names to pairfilenames().
  1326. X * 
  1327. X * Revision 4.2  83/12/02  22:47:45  wft
  1328. X * Added csh, red, and sl file name suffixes.
  1329. X * 
  1330. X * Revision 4.1  83/05/11  16:23:39  wft
  1331. X * Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
  1332. X * 1. added copying of path from workfile to RCS file, if RCS file is omitted;
  1333. X * 2. added getting the file status of RCS and working files;
  1334. X * 3. added ignoring of directories.
  1335. X * 
  1336. X * Revision 3.7  83/05/11  15:01:58  wft
  1337. X * Added comtable[] which pairs file name suffixes with comment leaders;
  1338. X * updated InitAdmin() accordingly.
  1339. X * 
  1340. X * Revision 3.6  83/04/05  14:47:36  wft
  1341. X * fixed Suffix in InitAdmin().
  1342. X * 
  1343. X * Revision 3.5  83/01/17  18:01:04  wft
  1344. X * Added getwd() and rename(); these can be removed by defining
  1345. X * V4_2BSD, since they are not needed in 4.2 bsd.
  1346. X * Changed sys/param.h to sys/types.h.
  1347. X *
  1348. X * Revision 3.4  82/12/08  21:55:20  wft
  1349. X * removed unused variable.
  1350. X *
  1351. X * Revision 3.3  82/11/28  20:31:37  wft
  1352. X * Changed mktempfile() to store the generated file names.
  1353. X * Changed getfullRCSname() to store the file and pathname, and to
  1354. X * delete leading "../" and "./".
  1355. X *
  1356. X * Revision 3.2  82/11/12  14:29:40  wft
  1357. X * changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(),
  1358. X * checksuffix(), checkfullpath(). Semaphore name generation updated.
  1359. X * mktempfile() now checks for nil path; freefilename initialized properly.
  1360. X * Added Suffix .h to InitAdmin. Added testprogram PAIRTEST.
  1361. X * Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here.
  1362. X *
  1363. X * Revision 3.1  82/10/18  14:51:28  wft
  1364. X * InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h).
  1365. X * renamed checkpath() to checkfullpath().
  1366. X */
  1367. X
  1368. X
  1369. X#include "rcsbase.h"
  1370. X#include <sys/types.h>
  1371. X#include <sys/stat.h>
  1372. X#include <sys/dir.h>
  1373. X
  1374. Xextern char * rindex();
  1375. Xextern char * mktemp();
  1376. Xextern FILE * fopen();
  1377. Xextern char * getwd();         /* get working directory; forward decl       */
  1378. Xextern int    stat(), fstat();
  1379. X
  1380. Xextern FILE * finptr;          /* RCS input file descriptor                 */
  1381. Xextern FILE * frewrite;        /* New RCS file descriptor                   */
  1382. Xextern char * RCSfilename, * workfilename; /* filenames                     */
  1383. Xstruct stat RCSstat, workstat; /* file status for RCS file and working file */
  1384. Xint    haveRCSstat,  haveworkstat; /* indicators if status availalble       */
  1385. X
  1386. X
  1387. Xchar tempfilename [NCPFN+10];  /* used for derived file names               */
  1388. Xchar sub1filename [NCPPN];     /* used for files path/file.sfx,v            */
  1389. Xchar sub2filename [NCPPN];     /* used for files path/RCS/file.sfx,v        */
  1390. Xchar semafilename [NCPPN];     /* name of semaphore file                    */
  1391. Xint  madesema;                 /* indicates whether a semaphore file has been set */
  1392. Xchar * tfnames[10];            /* temp. file names to be unlinked when finished   */
  1393. Xint  freefilename;             /* index of next free file name in tfnames[]  */
  1394. X
  1395. X
  1396. Xstruct compair {
  1397. X        char * suffix, * comlead;
  1398. X};
  1399. X
  1400. Xstruct compair comtable[] = {
  1401. X/* comtable pairs each filename suffix with a comment leader. The comment   */
  1402. X/* leader is placed before each line generated by the $Log keyword. This    */
  1403. X/* table is used to guess the proper comment leader from the working file's */
  1404. X/* suffix during initial ci (see InitAdmin()). Comment leaders are needed   */
  1405. X/* for languages without multiline comments; for others they are optional.  */
  1406. X        "c",   " * ",   /* C           */
  1407. X    "csh", "# ",    /* shell       */
  1408. X        "e",   "# ",    /* efl         */
  1409. X        "f",   "c ",    /* fortran     */
  1410. X        "h",   " * ",   /* C-header    */
  1411. X        "l",   " * ",   /* lex         NOTE: conflict between lex and franzlisp*/
  1412. X        "mac", "; ",    /* macro       vms or dec-20 or pdp-11 macro */
  1413. X    "me",  ".\\\" ",/* me-macros   t/nroff*/
  1414. X    "mm",  ".\\\" ",/* mm-macros   t/nroff*/
  1415. X    "ms",  ".\\\" ",/* ms-macros   t/nroff*/
  1416. X        "p",   " * ",   /* pascal      */
  1417. X    "pl",  "% ",    /* prolog      */
  1418. X        "r",   "# ",    /* ratfor      */
  1419. X        "red", "% ",    /* psl/rlisp   */
  1420. X
  1421. X#ifdef sparc
  1422. X        "s",   "! ",    /* assembler   */
  1423. X#endif
  1424. X#ifdef mc68000
  1425. X        "s",   "| ",    /* assembler   */
  1426. X#endif
  1427. X#ifdef pdp11
  1428. X        "s",   "/ ",    /* assembler   */
  1429. X#endif
  1430. X#ifdef vax
  1431. X        "s",   "# ",    /* assembler   */
  1432. X#endif
  1433. X
  1434. X        "sh",  "# ",    /* shell       */
  1435. X        "sl",  "% ",    /* psl         */
  1436. X        "red", "% ",    /* psl/rlisp   */
  1437. X        "cl",  ";;; ",  /* common lisp   */
  1438. X        "ml",  "; ",    /* mocklisp    */
  1439. X        "el",  "; ",    /* gnulisp     */
  1440. X    "tex", "% ",    /* tex           */
  1441. X        "y",   " * ",   /* yacc        */
  1442. X        "ye",  " * ",   /* yacc-efl    */
  1443. X        "yr",  " * ",   /* yacc-ratfor */
  1444. X        "",    "# ",    /* default for empty suffix */
  1445. X        nil,   ""       /* default for unknown suffix; must always be last */
  1446. X};
  1447. X
  1448. X
  1449. Xffclose(fptr)
  1450. XFILE * fptr;
  1451. X/* Function: checks ferror(fptr) and aborts the program if there were
  1452. X * errors; otherwise closes fptr.
  1453. X */
  1454. X{       if (ferror(fptr) || fclose(fptr)==EOF)
  1455. X                faterror("File read or write error; file system full?");
  1456. X}
  1457. X
  1458. X
  1459. X
  1460. Xint trysema(RCSname,makesema)
  1461. Xchar * RCSname; int makesema;
  1462. X/* Function: Checks whether a semaphore file exists for RCSname. If yes,
  1463. X * returns false. If not, creates one if makesema==true and returns true
  1464. X * if successful. If a semaphore file was created, madesema is set to true.
  1465. X * The name of the semaphore file is put into variable semafilename.
  1466. X */
  1467. X{
  1468. X        register char * tp, *sp, *lp;
  1469. X        int fdesc;
  1470. X
  1471. X        sp=RCSname;
  1472. X        lp = rindex(sp,'/');
  1473. X        if (lp==0) {
  1474. X                semafilename[0]='.'; semafilename[1]='/';
  1475. X                tp= &semafilename[2];
  1476. X        } else {
  1477. X                /* copy path */
  1478. X                tp=semafilename;
  1479. X                do *tp++ = *sp++; while (sp<=lp);
  1480. X        }
  1481. X        /*now insert `,' and append file name */
  1482. X        *tp++ = ',';
  1483. X        lp = rindex(sp, RCSSEP);
  1484. X        while (sp<lp) *tp++ = *sp++;
  1485. X        *tp++ = ','; *tp++ = '\0'; /* will be the same length as RCSname*/
  1486. X
  1487. X        madesema = false;
  1488. X        if (access(semafilename, 0) == 0) {
  1489. X                error("RCS file %s is in use",RCSname);
  1490. X                return false;
  1491. X        }
  1492. X        if (makesema) {
  1493. X                if ((fdesc=creat(semafilename, 000)) == -1) {
  1494. X                     error("Can't create semaphore file for RCS file %s",RCSname);
  1495. X                     return false;
  1496. X                } else
  1497. X                     VOID close(fdesc);
  1498. X                     madesema=true;
  1499. X        }
  1500. X        return true;
  1501. X}
  1502. X
  1503. X
  1504. Xrmsema()
  1505. X/* Function: delete the semaphore file if madeseam==true;
  1506. X * sets madesema to false.
  1507. X */
  1508. X{
  1509. X        if (madesema) {
  1510. X                madesema=false;
  1511. X                if (unlink(semafilename) == -1) {
  1512. X                        error("Can't find semaphore file %s",semafilename);
  1513. X                }
  1514. X        }
  1515. X}
  1516. X
  1517. X
  1518. X
  1519. XInitCleanup()
  1520. X{       freefilename =  0;  /* initialize pointer */
  1521. X}
  1522. X
  1523. X
  1524. Xcleanup()
  1525. X/* Function: closes input file and rewrite file.
  1526. X * Unlinks files in tfnames[], deletes semaphore file.
  1527. X */
  1528. X{
  1529. X        register int i;
  1530. X
  1531. X        if (finptr!=NULL)   VOID fclose(finptr);
  1532. X        if (frewrite!=NULL) VOID fclose(frewrite);
  1533. X        for (i=0; i<freefilename; i++) {
  1534. X            if (tfnames[i][0]!='\0')  VOID unlink(tfnames[i]);
  1535. X        }
  1536. X        InitCleanup();
  1537. X        rmsema();
  1538. X}
  1539. X
  1540. X
  1541. Xchar * mktempfile(fullpath,filename)
  1542. Xregister char * fullpath, * filename;
  1543. X/* Function: Creates a unique filename using the process id and stores it
  1544. X * into a free slot in tfnames. The filename consists of the path contained
  1545. X * in fullpath concatenated with filename. filename should end in "XXXXXX".
  1546. X * Because of storage in tfnames, cleanup() can unlink the file later.
  1547. X * freefilename indicates the lowest unoccupied slot in tfnames.
  1548. X * Returns a pointer to the filename created.
  1549. X * Example use: mktempfile("/tmp/", somefilename)
  1550. X */
  1551. X{
  1552. X        register char * lastslash, *tp;
  1553. X        if ((tp=tfnames[freefilename])==nil)
  1554. X              tp=tfnames[freefilename] = talloc(NCPPN);
  1555. X        if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
  1556. X                /* copy path */
  1557. X                while (fullpath<=lastslash) *tp++ = *fullpath++;
  1558. X        }
  1559. X        while (*tp++ = *filename++);
  1560. X        return (mktemp(tfnames[freefilename++]));
  1561. X}
  1562. X
  1563. X
  1564. X
  1565. X
  1566. Xchar * bindex(sp,c)
  1567. Xregister char * sp, c;
  1568. X/* Function: Finds the last occurrence of character c in string sp
  1569. X * and returns a pointer to the character just beyond it. If the
  1570. X * character doesn't occur in the string, sp is returned.
  1571. X */
  1572. X{       register char * r;
  1573. X        r = sp;
  1574. X        while (*sp) {
  1575. X                if (*sp++ == c) r=sp;
  1576. X        }
  1577. X        return r;
  1578. X}
  1579. X
  1580. X
  1581. X
  1582. X
  1583. X
  1584. XInitAdmin()
  1585. X/* function: initializes an admin node */
  1586. X{       register char * Suffix;
  1587. X        register int i;
  1588. X
  1589. X        Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
  1590. X        StrictLocks=STRICT_LOCKING;
  1591. X
  1592. X        /* guess the comment leader from the suffix*/
  1593. X        Suffix=bindex(workfilename, '.');
  1594. X        if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
  1595. X        for (i=0;;i++) {
  1596. X                if (comtable[i].suffix==nil) {
  1597. X                        Comment=comtable[i].comlead; /*default*/
  1598. X                        break;
  1599. X                } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
  1600. X                        Comment=comtable[i].comlead; /*default*/
  1601. X                        break;
  1602. X                }
  1603. X        }
  1604. X        Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
  1605. X}
  1606. X
  1607. X
  1608. X
  1609. Xchar * findpairfile(argc, argv, fname)
  1610. Xint argc; char * argv[], *fname;
  1611. X/* Function: Given a filename fname, findpairfile scans argv for a pathname
  1612. X * ending in fname. If found, returns a pointer to the pathname, and sets
  1613. X * the corresponding pointer in argv to nil. Otherwise returns fname.
  1614. X * argc indicates the number of entries in argv. Some of them may be nil.
  1615. X */
  1616. X{
  1617. X        register char * * next, * match;
  1618. X        register int count;
  1619. X
  1620. X        for (next = argv, count = argc; count>0; next++,count--) {
  1621. X                if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
  1622. X                        /* bindex finds the beginning of the file name stem */
  1623. X                        match= *next;
  1624. X                        *next=nil;
  1625. X                        return match;
  1626. X                }
  1627. X        }
  1628. X        return fname;
  1629. X}
  1630. X
  1631. X
  1632. Xint pairfilenames(argc, argv, mustread, tostdout)
  1633. Xint argc; char ** argv; int mustread, tostdout;
  1634. X/* Function: Pairs the filenames pointed to by argv; argc indicates
  1635. X * how many there are.
  1636. X * Places a pointer to the RCS filename into RCSfilename,
  1637. X * and a pointer to the name of the working file into workfilename.
  1638. X * If both the workfilename and the RCS filename are given, and tostdout
  1639. X * is true, a warning is printed.
  1640. X *
  1641. X * If the working file exists, places its status into workstat and
  1642. X * sets haveworkstat to 0; otherwise, haveworkstat is set to -1;
  1643. X * Similarly for the RCS file and the variables RCSstat and haveRCSstat.
  1644. X *
  1645. X * If the RCS file exists, it is opened for reading, the file pointer
  1646. X * is placed into finptr, and the admin-node is read in; returns 1.
  1647. X * If the RCS file does not exist and mustread==true, an error is printed
  1648. X * and 0 returned.
  1649. X * If the RCS file does not exist and mustread==false, the admin node
  1650. X * is initialized to empty (Head, AccessList, Locks, Symbols, StrictLocks, Dbranch)
  1651. X * and -1 returned.
  1652. X *
  1653. X * 0 is returned on all errors. Files that are directories are errors.
  1654. X * Also calls InitCleanup();
  1655. X */
  1656. X{
  1657. X        register char * sp, * tp;
  1658. X        char * lastsep, * purefname, * pureRCSname;
  1659. X        int opened, returncode;
  1660. X        char * RCS1;
  1661. X    char prefdir[NCPPN];
  1662. X
  1663. X        if (*argv == nil) return 0; /* already paired filename */
  1664. X    if (rindex(*argv,KDELIM)!=0) {
  1665. X        /* KDELIM causes havoc in keyword expansion    */
  1666. X        error("RCS file name may not contain %c",KDELIM);
  1667. X        return 0;
  1668. X    }
  1669. X        InitCleanup();
  1670. X
  1671. X        /* first check suffix to see whether it is an RCS file or not */
  1672. X        purefname=bindex(*argv, '/'); /* skip path */
  1673. X        lastsep=rindex(purefname, RCSSEP);
  1674. X        if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
  1675. X                /* RCS file name given*/
  1676. X                RCS1=(*argv); pureRCSname=purefname;
  1677. X                /* derive workfilename*/
  1678. X                sp = purefname; tp=tempfilename;
  1679. X                while (sp<lastsep) *tp++ = *sp++; *tp='\0';
  1680. X                /* try to find workfile name among arguments */
  1681. X                workfilename=findpairfile(argc-1,argv+1,tempfilename);
  1682. X                if (strlen(pureRCSname)>NCPFN) {
  1683. X                        error("RCS file name %s too long",RCS1);
  1684. X                        return 0;
  1685. X                }
  1686. X        } else {
  1687. X                /* working file given; now try to find RCS file */
  1688. X                workfilename= *argv;
  1689. X                /* derive RCS file name*/
  1690. X                sp=purefname; tp=tempfilename;
  1691. X                while (*tp++ = *sp++);
  1692. X                *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp++='\0';
  1693. X                /* Try to find RCS file name among arguments*/
  1694. X                RCS1=findpairfile(argc-1,argv+1,tempfilename);
  1695. X                pureRCSname=bindex(RCS1, '/');
  1696. X                if (strlen(pureRCSname)>NCPFN) {
  1697. X                        error("working file name %s too long",workfilename);
  1698. X                        return 0;
  1699. X                }
  1700. X        }
  1701. X        /* now we have a (tentative) RCS filename in RCS1 and workfilename  */
  1702. X        /* First, get status of workfilename */
  1703. X        haveworkstat=stat(workfilename, &workstat);
  1704. X        if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
  1705. X                diagnose("Directory %s ignored",workfilename);
  1706. X                return 0;
  1707. X        }
  1708. X        /* Second, try to find the right RCS file */
  1709. X        if (pureRCSname!=RCS1) {
  1710. X                /* a path for RCSfile is given; single RCS file to look for */
  1711. X                finptr=fopen(RCSfilename=RCS1, "r");
  1712. X                if (finptr!=NULL) {
  1713. X                    returncode=1;
  1714. X                } else { /* could not open */
  1715. X                    if (access(RCSfilename,0)==0) {
  1716. X                        error("Can't open existing %s", RCSfilename);
  1717. X                        return 0;
  1718. X                    }
  1719. X                    if (mustread) {
  1720. X                        error("Can't find %s", RCSfilename);
  1721. X                        return 0;
  1722. X                    } else {
  1723. X                        /* initialize if not mustread */
  1724. X                        returncode = -1;
  1725. X                    }
  1726. X                }
  1727. X        } else {
  1728. X        /* no path for RCS file name. Prefix it with path of work */
  1729. X        /* file if RCS file omitted. Make a second name including */
  1730. X        /* RCSDIR and try to open that one first.                 */
  1731. X        sub1filename[0]=sub2filename[0]= '\0';
  1732. X        if (RCS1==tempfilename) {
  1733. X            /* RCS file name not given; prepend work path */
  1734. X            sp= *argv; tp= sub1filename;
  1735. X            while (sp<purefname) *tp++ = *sp ++;
  1736. X            *tp='\0';
  1737. X            VOID strcpy(sub2filename,sub1filename); /* second one */
  1738. X        }
  1739. X        VOID strcat(sub1filename,RCSDIR);
  1740. X        VOID strcpy(prefdir,sub1filename); /* preferred directory for RCS file*/
  1741. X        VOID strcat(sub1filename,RCS1); VOID strcat(sub2filename,RCS1);
  1742. X
  1743. X
  1744. X                opened=(
  1745. X        ((finptr=fopen(RCSfilename=sub1filename, "r"))!=NULL) ||
  1746. X        ((finptr=fopen(RCSfilename=sub2filename,"r"))!=NULL) );
  1747. X
  1748. X                if (opened) {
  1749. X                        /* open succeeded */
  1750. X                        returncode=1;
  1751. X                } else {
  1752. X                        /* open failed; may be read protected */
  1753. X            if ((access(RCSfilename=sub1filename,0)==0) ||
  1754. X                (access(RCSfilename=sub2filename,0)==0)) {
  1755. X                                error("Can't open existing %s",RCSfilename);
  1756. X                                return 0;
  1757. X                        }
  1758. X                        if (mustread) {
  1759. X                error("Can't find %s nor %s",sub1filename,sub2filename);
  1760. X                                return 0;
  1761. X                        } else {
  1762. X                                /* initialize new file. Put into ./RCS if possible, strip off suffix*/
  1763. X                RCSfilename= (access(prefdir,0)==0)?sub1filename:sub2filename;
  1764. X                                returncode= -1;
  1765. X                        }
  1766. X                }
  1767. X        }
  1768. X
  1769. X        if (returncode == 1) { /* RCS file open */
  1770. X                haveRCSstat=fstat(fileno(finptr),&RCSstat);
  1771. X                if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
  1772. X                        diagnose("Directory %s ignored",RCSfilename);
  1773. X                        return 0;
  1774. X                }
  1775. X                Lexinit(); getadmin();
  1776. X        } else {  /* returncode == -1; RCS file nonexisting */
  1777. X                haveRCSstat = -1;
  1778. X                InitAdmin();
  1779. X        };
  1780. X
  1781. X        if (tostdout&&
  1782. X            !(RCS1==tempfilename||workfilename==tempfilename))
  1783. X                /*The last term determines whether a pair of        */
  1784. X                /* file names was given in the argument list        */
  1785. X                warn("Option -p is set; ignoring output file %s",workfilename);
  1786. X
  1787. X        return returncode;
  1788. X}
  1789. X
  1790. X
  1791. Xchar * getfullRCSname()
  1792. X/* Function: returns a pointer to the full path name of the RCS file.
  1793. X * Calls getwd(), but only once.
  1794. X * removes leading "../" and "./".
  1795. X */
  1796. X{       static char pathbuf[NCPPN];
  1797. X        static char namebuf[NCPPN];
  1798. X        static int  pathlength;
  1799. X
  1800. X        register char * realname, * lastpathchar;
  1801. X        register int  dotdotcounter, realpathlength;
  1802. X
  1803. X        if (*RCSfilename=='/') {
  1804. X                return(RCSfilename);
  1805. X        } else {
  1806. X                if (pathlength==0) { /*call curdir for the first time*/
  1807. X                    if (getwd(pathbuf)==NULL)
  1808. X                        faterror("Can't build current directory path");
  1809. X                    pathlength=strlen(pathbuf);
  1810. X                    if (!((pathlength==1) && (pathbuf[0]=='/'))) {
  1811. X                        pathbuf[pathlength++]='/';
  1812. X                        /* Check needed because some getwd implementations */
  1813. X                        /* generate "/" for the root.                      */
  1814. X                    }
  1815. X                }
  1816. X                /*the following must be redone since RCSfilename may change*/
  1817. X                /* find how many ../ to remvove from RCSfilename */
  1818. X                dotdotcounter =0;
  1819. X                realname = RCSfilename;
  1820. X                while( realname[0]=='.' &&
  1821. X                      (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
  1822. X                        if (realname[1]=='/') {
  1823. X                            /* drop leading ./ */
  1824. X                            realname += 2;
  1825. X                        } else {
  1826. X                            /* drop leading ../ and remember */
  1827. X                            dotdotcounter++;
  1828. X                            realname += 3;
  1829. X                        }
  1830. X                }
  1831. X                /* now remove dotdotcounter trailing directories from pathbuf*/
  1832. X                lastpathchar=pathbuf + pathlength-1;
  1833. X                while (dotdotcounter>0 && lastpathchar>pathbuf) {
  1834. X                    /* move pointer backwards over trailing directory */
  1835. X                    lastpathchar--;
  1836. X                    if (*lastpathchar=='/') {
  1837. X                        dotdotcounter--;
  1838. X                    }
  1839. X                }
  1840. X                if (dotdotcounter>0) {
  1841. X                    error("Can't generate full path name for RCS file");
  1842. X                    return RCSfilename;
  1843. X                } else {
  1844. X                    /* build full path name */
  1845. X                    realpathlength=lastpathchar-pathbuf+1;
  1846. X                    VOID strncpy(namebuf,pathbuf,realpathlength);
  1847. X                    VOID strcpy(&namebuf[realpathlength],realname);
  1848. X                    return(namebuf);
  1849. X                }
  1850. X        }
  1851. X}
  1852. X
  1853. X
  1854. X
  1855. Xint trydiraccess(filename)
  1856. Xchar * filename;
  1857. X/* checks write permission in directory of filename and returns
  1858. X * true if writable, false otherwise
  1859. X */
  1860. X{
  1861. X        char pathname[NCPPN];
  1862. X        register char * tp, *sp, *lp;
  1863. X        lp = rindex(filename,'/');
  1864. X        if (lp==0) {
  1865. X                /* check current directory */
  1866. X                if (access(".",2)==0)
  1867. X                        return true;
  1868. X                else {
  1869. X                        error("Current directory not writable");
  1870. X                        return false;
  1871. X                }
  1872. X        }
  1873. X        /* copy path */
  1874. X        sp=filename;
  1875. X        tp=pathname;
  1876. X        do *tp++ = *sp++; while (sp<=lp);
  1877. X        *tp='\0';
  1878. X        if (access(pathname,2)==0)
  1879. X                return true;
  1880. X        else {
  1881. X                error("Directory %s not writable", pathname);
  1882. X                return false;
  1883. X        }
  1884. X}
  1885. X
  1886. X
  1887. X
  1888. X#ifndef V4_2BSD
  1889. X/* rename() and getwd() will be provided in bsd 4.2 */
  1890. X
  1891. X
  1892. Xint rename(from, to)
  1893. Xchar * from, *to;
  1894. X/* Function: renames a file with the name given by from to the name given by to.
  1895. X * unlinks the to-file if it already exists. returns -1 on error, 0 otherwise.
  1896. X */
  1897. X{       VOID unlink(to);      /* no need to check return code; will be caught by link*/
  1898. X                         /* no harm done if file "to" does not exist            */
  1899. X        if (link(from,to)<0) return -1;
  1900. X        return(unlink(from));
  1901. X}
  1902. X
  1903. X
  1904. X
  1905. X#define dot     "."
  1906. X#define dotdot  ".."
  1907. X
  1908. X
  1909. X
  1910. Xchar * getwd(name)
  1911. Xchar * name;
  1912. X/* Function: places full pathname of current working directory into name and
  1913. X * returns name on success, NULL on failure.
  1914. X * getwd is an adaptation of pwd. May not return to the current directory on
  1915. X * failure.
  1916. X */
  1917. X{
  1918. X        FILE    *file;
  1919. X        struct  stat    d, dd;
  1920. X        char buf[2];    /* to NUL-terminate dir.d_name */
  1921. X        struct  direct  dir;
  1922. X
  1923. X        int rdev, rino;
  1924. X        int off;
  1925. X        register i,j;
  1926. X
  1927. X        name[off= 0] = '/';
  1928. X        name[1] = '\0';
  1929. X        buf[0] = '\0';
  1930. X        if (stat("/", &d)<0) return NULL;
  1931. X        rdev = d.st_dev;
  1932. X        rino = d.st_ino;
  1933. X        for (;;) {
  1934. X                if (stat(dot, &d)<0) return NULL;
  1935. X                if (d.st_ino==rino && d.st_dev==rdev) {
  1936. X                        if (name[off] == '/') name[off] = '\0';
  1937. X                        chdir(name); /*change back to current directory*/
  1938. X                        return name;
  1939. X                }
  1940. X                if ((file = fopen(dotdot,"r")) == NULL) return NULL;
  1941. X                if (fstat(fileno(file), &dd)<0) goto fail;
  1942. X                chdir(dotdot);
  1943. X                if(d.st_dev == dd.st_dev) {
  1944. X                        if(d.st_ino == dd.st_ino) {
  1945. X                            if (name[off] == '/') name[off] = '\0';
  1946. X                            chdir(name); /*change back to current directory*/
  1947. X                            VOID fclose(file);
  1948. X                            return name;
  1949. X                        }
  1950. X                        do {
  1951. X                            if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
  1952. X                                goto fail;
  1953. X                        } while (dir.d_ino != d.st_ino);
  1954. X                }
  1955. X                else do {
  1956. X                        if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
  1957. X                            goto fail;
  1958. X                        }
  1959. X                        if (dir.d_ino == 0)
  1960. X                dd.st_ino = d.st_ino + 1;
  1961. X                        else if (stat(dir.d_name, &dd) < 0)
  1962. X                goto fail;
  1963. X                } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
  1964. X                VOID fclose(file);
  1965. X
  1966. X                /* concatenate file name */
  1967. X                i = -1;
  1968. X                while (dir.d_name[++i] != 0);
  1969. X                for(j=off+1; j>0; --j)
  1970. X                        name[j+i+1] = name[j];
  1971. X                off=i+off+1;
  1972. X                name[i+1] = '/';
  1973. X                for(--i; i>=0; --i)
  1974. X                        name[i+1] = dir.d_name[i];
  1975. X        } /* end for */
  1976. X
  1977. Xfail:   VOID fclose(file);
  1978. X        return NULL;
  1979. X}
  1980. X
  1981. X
  1982. X#endif
  1983. X
  1984. X
  1985. X#ifdef PAIRTEST
  1986. X/* test program for pairfilenames() and getfullRCSname() */
  1987. Xchar * workfilename, *RCSfilename;
  1988. Xextern int quietflag;
  1989. X
  1990. Xmain(argc, argv)
  1991. Xint argc; char *argv[];
  1992. X{
  1993. X        int result;
  1994. X        int initflag,tostdout;
  1995. X        quietflag=tostdout=initflag=false;
  1996. X        cmdid="pair";
  1997. X
  1998. X        while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
  1999. X                switch ((*argv)[1]) {
  2000. X
  2001. X                case 'p':       tostdout=true;
  2002. X                                break;
  2003. X                case 'i':       initflag=true;
  2004. X                                break;
  2005. X                case 'q':       quietflag=true;
  2006. X                                break;
  2007. X                default:        error("unknown option: %s", *argv);
  2008. X                                break;
  2009. X                }
  2010. X        }
  2011. X
  2012. X        do {
  2013. X                RCSfilename=workfilename=nil;
  2014. X                result=pairfilenames(argc,argv,!initflag,tostdout);
  2015. X                if (result!=0) {
  2016. X                     diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
  2017. X                     diagnose("Full RCS file name: %s", getfullRCSname());
  2018. X                }
  2019. X                switch (result) {
  2020. X                        case 0: continue; /* already paired file */
  2021. X
  2022. X                        case 1: if (initflag) {
  2023. X                                    error("RCS file %s exists already",RCSfilename);
  2024. X                                } else {
  2025. X                                    diagnose("RCS file %s exists",RCSfilename);
  2026. X                                }
  2027. X                                VOID fclose(finptr);
  2028. X                                break;
  2029. X
  2030. X                        case -1:diagnose("RCS file does not exist");
  2031. X                                break;
  2032. X                }
  2033. X
  2034. X        } while (++argv, --argc>=1);
  2035. X
  2036. X}
  2037. X#endif
  2038. X@
  2039. X
  2040. X
  2041. X4.8.2.1
  2042. Xlog
  2043. X@Start of Amiga RCS port branch.
  2044. X@
  2045. Xtext
  2046. X@d6 1
  2047. Xa6 5
  2048. X<<<<<<< rcsfnms.c
  2049. X rcsid[]= "$Id: rcsfnms.c,v 4.8.1.1 89/08/11 01:42:32 rsbx Exp Locker: rsbx $ Purdue CS";
  2050. X=======
  2051. X rcsid[]= "$Id: rcsfnms.c,v 1.2 89/09/17 13:35:38 rick Exp $ Purdue CS";
  2052. X>>>>>>> 1.2
  2053. Xa44 11
  2054. X<<<<<<< rcsfnms.c
  2055. X * Revision 4.8.1.1  89/08/11  01:42:32  rsbx
  2056. X * Start of cbmvax RCS source branch.
  2057. X=======
  2058. X * Revision 1.2  89/09/17  13:35:38  rick
  2059. X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
  2060. X * All changes done with conditional compile (#ifdef AMIGA).  This version
  2061. X * compiles correctly with Lattice C version 5.02 or later.
  2062. X>>>>>>> 1.2
  2063. X * 
  2064. X<<<<<<< rcsfnms.c
  2065. Xa45 3
  2066. X * checked in with -k by rsbx at 89.08.10.16.20.00.
  2067. X * 
  2068. X * Revision 4.8  89/05/01  15:09:41  narten
  2069. Xa53 8
  2070. X=======
  2071. X * Revision 1.3  89/09/16  09:43:16  rick
  2072. X * Modified AMIGA changes to work with Lattice C
  2073. X * 
  2074. X * Revision 1.2  88/09/03  15:10:24  rick
  2075. X * Port to AmigaDos.  All done with conditional compiles
  2076. X * 
  2077. X>>>>>>> 1.2
  2078. Xd115 2
  2079. Xa116 3
  2080. X#ifdef AMIGA
  2081. X#include "stat.h"
  2082. X#else
  2083. Xa119 2
  2084. X#endif
  2085. X#include "rcsbase.h"
  2086. Xa120 2
  2087. Xextern int errno;
  2088. X
  2089. Xd201 1
  2090. Xa201 9
  2091. X{
  2092. X    if (fptr == NULL)
  2093. X        return;
  2094. X#ifdef AMIGA
  2095. X    if (ferror(fptr))
  2096. X        warn("File read or write error %d; file system full?",errno);
  2097. X    fclose(fptr);
  2098. X#else
  2099. X        if (ferror(fptr) || (fclose(fptr)==EOF))
  2100. Xa202 1
  2101. X#endif
  2102. Xa220 3
  2103. X#ifdef AMIGA
  2104. X                tp = &semafilename[0];
  2105. X#else
  2106. Xa222 1
  2107. X#endif
  2108. Xa299 1
  2109. X<<<<<<< rcsfnms.c
  2110. Xa301 14
  2111. X=======
  2112. X        lastfilename++;
  2113. X        if ((tp=tfnames[lastfilename])==nil)
  2114. X              tp=tfnames[lastfilename] = malloc(NCPPN);
  2115. X#ifdef AMIGA
  2116. X    *tp = 0;
  2117. X    if (fullpath!=nil) {
  2118. X        if ((lastslash=rindex(fullpath,'/')) == NULL)
  2119. X            lastslash = rindex(fullpath,':');
  2120. X        if (lastslash != NULL)
  2121. X                    while (fullpath<=lastslash) *tp++ = *fullpath++;
  2122. X        }
  2123. X#else
  2124. X>>>>>>> 1.2
  2125. Xa305 1
  2126. X#endif
  2127. Xa450 1
  2128. X#ifndef AMIGA
  2129. Xa454 1
  2130. X#endif
  2131. Xa516 1
  2132. X#ifndef AMIGA
  2133. Xa521 1
  2134. X#endif
  2135. Xa612 3
  2136. X#ifdef AMIGA
  2137. X                return true;
  2138. X#else
  2139. Xa618 1
  2140. X#endif
  2141. Xd638 1
  2142. Xa638 1
  2143. X#ifndef AMIGA
  2144. Xa648 1
  2145. X#endif
  2146. Xa649 3
  2147. X#ifdef AMIGA
  2148. X#include <libraries/dosextens.h>
  2149. X#include <exec/memory.h>
  2150. Xa650 3
  2151. Xextern struct Process *FindTask();
  2152. Xextern struct FileLock *ParentDir(), *Lock();
  2153. Xextern char *AllocMem();
  2154. Xa651 51
  2155. Xchar *followpath(lock,level)
  2156. Xstruct FileLock *lock;
  2157. Xint        level;
  2158. X{
  2159. X    struct FileInfoBlock *fib;
  2160. X    struct FileLock *newlock;
  2161. X    static char pathbuf[NCPPN];
  2162. X
  2163. X    if (! lock)
  2164. X        return(pathbuf);
  2165. X    if (level == 0)
  2166. X        pathbuf[0] = 0;
  2167. X    fib = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CLEAR);
  2168. X    if (fib == NULL) {
  2169. X        printf("followpath: Out of Memory\n");
  2170. X        return(pathbuf);
  2171. X        }
  2172. X    newlock = ParentDir(lock);
  2173. X    followpath(newlock,1);
  2174. X    if (Examine(lock,fib)) {
  2175. X        if (fib->fib_FileName[0] > ' ')
  2176. X            strcat(pathbuf,fib->fib_FileName);
  2177. X        else
  2178. X            strcat(pathbuf,"RAM");
  2179. X        if (newlock == NULL)
  2180. X            strcat(pathbuf,":");
  2181. X        else
  2182. X            strcat(pathbuf,"/");
  2183. X        }
  2184. X    UnLock(lock);
  2185. X    if (fib)
  2186. X        FreeMem(fib,(long) sizeof(struct FileInfoBlock));
  2187. X    return(pathbuf);
  2188. X}
  2189. X
  2190. Xchar *getwd(name)
  2191. Xchar    *name;
  2192. X{
  2193. X    struct FileLock *oldlock;
  2194. X
  2195. X    oldlock = Lock("",ACCESS_READ);
  2196. X    if (oldlock == NULL)
  2197. X        return(NULL);
  2198. X    strcpy(name,followpath(oldlock,0));
  2199. X    if (name[strlen(name)-1] == '/')
  2200. X        name[strlen(name)-1] = 0;
  2201. X    return(name);
  2202. X}
  2203. X
  2204. X#else
  2205. X
  2206. Xa727 1
  2207. X#endif
  2208. Xa782 33
  2209. X}
  2210. X#endif
  2211. X
  2212. X#ifdef AMIGA
  2213. Xchar *mktemp(template)
  2214. Xchar *template;
  2215. X{
  2216. X    register char *cp;
  2217. X    register unsigned long val;
  2218. X
  2219. X    cp = template;
  2220. X    cp += strlen(cp);
  2221. X    for (val = (unsigned long) FindTask(0L) ; ; )
  2222. X        if (*--cp == 'X') {
  2223. X            *cp = val%10 + '0';
  2224. X            val /= 10;
  2225. X        } else if (*cp != '.')
  2226. X            break;
  2227. X
  2228. X    if (*++cp != 0) {
  2229. X        *cp = 'A';
  2230. X        while (access(template, 0) == 0) {
  2231. X            if (*cp == 'Z') {
  2232. X                *template = 0;
  2233. X                break;
  2234. X            }
  2235. X            ++*cp;
  2236. X        }
  2237. X    } else {
  2238. X        if (access(template, 0) == 0)
  2239. X            *template = 0;
  2240. X    }
  2241. X    return template;
  2242. X@
  2243. X
  2244. X
  2245. X4.8.2.2
  2246. Xlog
  2247. X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  2248. Xsources I have here (and are later than the ones Rick used).
  2249. X@
  2250. Xtext
  2251. X@d6 5
  2252. Xa10 1
  2253. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.1 89/10/13 19:18:32 rsbx Exp Locker: rsbx $ Purdue CS";
  2254. Xd49 1
  2255. Xa49 3
  2256. X * Revision 4.8.2.1  89/10/13  19:18:32  rsbx
  2257. X * Start of Amiga RCS port branch.
  2258. X * 
  2259. Xd52 6
  2260. Xd59 1
  2261. Xd72 8
  2262. Xd276 1
  2263. Xa276 1
  2264. X        *tp++ = ','; *tp = '\0'; /* will be the same length as RCSname*/
  2265. Xd344 1
  2266. Xd347 4
  2267. Xd360 1
  2268. Xd499 1
  2269. Xa499 1
  2270. X                *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp='\0';
  2271. Xa719 1
  2272. X#ifdef RICKS
  2273. Xa774 10
  2274. X#else
  2275. Xchar *getwd(char *name)
  2276. X    {
  2277. X    if (getcd(0, name) == 0)
  2278. X        {
  2279. X        return name;
  2280. X        }
  2281. X    return NULL;
  2282. X    }
  2283. X#endif RICKS
  2284. X@
  2285. X
  2286. X
  2287. X4.8.2.3
  2288. Xlog
  2289. X@More changes to make Amiga port work.
  2290. X@
  2291. Xtext
  2292. X@d6 1
  2293. Xa6 1
  2294. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.2 89/10/15 15:44:18 rsbx Exp $ Purdue CS";
  2295. Xa44 4
  2296. X * Revision 4.8.2.2  89/10/15  15:44:18  rsbx
  2297. X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  2298. X * sources I have here (and are later than the ones Rick used).
  2299. X * 
  2300. Xd245 1
  2301. Xa245 1
  2302. X        tp = &semafilename[0];
  2303. Xa260 5
  2304. X#ifdef DEBUG
  2305. X    fprintf(stderr,"semafilename = %%%s%%\n", semafilename);
  2306. X    fflush(stderr);
  2307. X#endif
  2308. X
  2309. Xd529 1
  2310. Xd549 1
  2311. Xa549 21
  2312. X                struct stat pdirstat;
  2313. X
  2314. X                if (stat(prefdir,&pdirstat))
  2315. X                    {
  2316. X                    RCSfilename=sub2filename;
  2317. X                    }
  2318. X                else
  2319. X                    {
  2320. X#ifdef AMIGA
  2321. X                    if (pdirstat.st_type > 0)
  2322. X#else
  2323. X                    if ((pdirstat.st_mode & S_IFMT) != S_IFREG)
  2324. X#endif
  2325. X                        {
  2326. X                        RCSfilename = sub1filename;
  2327. X                        }
  2328. X                    else
  2329. X                        {
  2330. X                        RCSfilename = sub2filename;
  2331. X                        }
  2332. X                    }
  2333. X@
  2334. X
  2335. X
  2336. X4.8.2.4
  2337. Xlog
  2338. X@Changed file path handling to deal with Amiga file path sematics.
  2339. X@
  2340. Xtext
  2341. X@d2 1
  2342. Xa2 1
  2343. X *             RCS file name handling
  2344. Xd6 1
  2345. Xa6 1
  2346. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.3 89/10/15 18:27:52 rsbx Exp $ Purdue CS";
  2347. Xd9 4
  2348. Xa12 4
  2349. X *             creation and deletion of semaphorefile,
  2350. X *             creation of temporary filenames and cleanup()
  2351. X *             pairing of RCS file names and working file names.
  2352. X *             Testprogram: define PAIRTEST
  2353. Xa44 3
  2354. X * Revision 4.8.2.3  89/10/15  18:27:52  rsbx
  2355. X * More changes to make Amiga port work.
  2356. X * 
  2357. Xd171 1
  2358. Xa171 1
  2359. X    "c",   " * ",   /* C           */
  2360. Xd173 5
  2361. Xa177 5
  2362. X    "e",   "# ",    /* efl         */
  2363. X    "f",   "c ",    /* fortran     */
  2364. X    "h",   " * ",   /* C-header    */
  2365. X    "l",   " * ",   /* lex         NOTE: conflict between lex and franzlisp*/
  2366. X    "mac", "; ",    /* macro       vms or dec-20 or pdp-11 macro */
  2367. Xd181 1
  2368. Xa181 1
  2369. X    "p",   " * ",   /* pascal      */
  2370. Xd183 2
  2371. Xa184 2
  2372. X    "r",   "# ",    /* ratfor      */
  2373. X    "red", "% ",    /* psl/rlisp   */
  2374. Xd187 1
  2375. Xa187 1
  2376. X    "s",   "! ",    /* assembler   */
  2377. Xd190 1
  2378. Xa190 1
  2379. X    "s",   "| ",    /* assembler   */
  2380. Xd193 1
  2381. Xa193 1
  2382. X    "s",   "/ ",    /* assembler   */
  2383. Xd196 1
  2384. Xa196 1
  2385. X    "s",   "# ",    /* assembler   */
  2386. Xa197 4
  2387. X#ifdef AMIGA
  2388. X    "asm", "* ",    /* assembler   */
  2389. X    "i",   "* ",    /* assembler include */
  2390. X#endif
  2391. Xd199 6
  2392. Xa204 6
  2393. X    "sh",  "# ",    /* shell       */
  2394. X    "sl",  "% ",    /* psl         */
  2395. X    "red", "% ",    /* psl/rlisp   */
  2396. X    "cl",  ";;; ",  /* common lisp   */
  2397. X    "ml",  "; ",    /* mocklisp    */
  2398. X    "el",  "; ",    /* gnulisp     */
  2399. Xd206 5
  2400. Xa210 5
  2401. X    "y",   " * ",   /* yacc        */
  2402. X    "ye",  " * ",   /* yacc-efl    */
  2403. X    "yr",  " * ",   /* yacc-ratfor */
  2404. X    "",    "# ",    /* default for empty suffix */
  2405. X    nil,   ""       /* default for unknown suffix; must always be last */
  2406. Xd227 2
  2407. Xa228 2
  2408. X    if (ferror(fptr) || (fclose(fptr)==EOF))
  2409. X        faterror("File read or write error; file system full?");
  2410. Xd242 2
  2411. Xa243 2
  2412. X    register char * tp, *sp, *lp;
  2413. X    int fdesc;
  2414. Xd245 3
  2415. Xa247 1
  2416. X    sp=RCSname;
  2417. Xa248 17
  2418. X    if (lp = index(sp,':'))            /* volume: ? */
  2419. X        {
  2420. X        if (tp = rindex(lp,'/'))    /* volume:path/ ? */
  2421. X            {
  2422. X            lp = tp;
  2423. X            }
  2424. X        }
  2425. X    else
  2426. X        {
  2427. X        lp = rindex(sp,'/');
  2428. X        }
  2429. X#else
  2430. X    lp = rindex(sp,'/');
  2431. X#endif
  2432. X
  2433. X    if (lp==0) {
  2434. X#ifdef AMIGA
  2435. Xd251 2
  2436. Xa252 2
  2437. X        semafilename[0]='.'; semafilename[1]='/';
  2438. X        tp= &semafilename[2];
  2439. Xd254 10
  2440. Xa263 10
  2441. X    } else {
  2442. X        /* copy path */
  2443. X        tp=semafilename;
  2444. X        do *tp++ = *sp++; while (sp<=lp);
  2445. X    }
  2446. X    /*now insert `,' and append file name */
  2447. X    *tp++ = ',';
  2448. X    lp = rindex(sp, RCSSEP);
  2449. X    while (sp<lp) *tp++ = *sp++;
  2450. X    *tp++ = ','; *tp = '\0'; /* will be the same length as RCSname*/
  2451. Xd270 14
  2452. Xa283 14
  2453. X    madesema = false;
  2454. X    if (access(semafilename, 0) == 0) {
  2455. X        error("RCS file %s is in use",RCSname);
  2456. X        return false;
  2457. X    }
  2458. X    if (makesema) {
  2459. X        if ((fdesc=creat(semafilename, 000)) == -1) {
  2460. X            error("Can't create semaphore file for RCS file %s",RCSname);
  2461. X            return false;
  2462. X        }
  2463. X        VOID close(fdesc);
  2464. X        madesema=true;
  2465. X    }
  2466. X    return true;
  2467. Xd292 7
  2468. Xa298 7
  2469. X    if (madesema) {
  2470. X        madesema=false;
  2471. X        if (unlink(semafilename) == -1) {
  2472. X            error("Can't find semaphore file %s",semafilename);
  2473. X        }
  2474. X    }
  2475. X}
  2476. Xd312 1
  2477. Xa312 1
  2478. X    register int i;
  2479. Xd314 7
  2480. Xa320 7
  2481. X    if (finptr!=NULL)   VOID fclose(finptr);
  2482. X    if (frewrite!=NULL) VOID fclose(frewrite);
  2483. X    for (i=0; i<freefilename; i++) {
  2484. X        if (tfnames[i][0]!='\0')  VOID unlink(tfnames[i]);
  2485. X    }
  2486. X    InitCleanup();
  2487. X    rmsema();
  2488. Xd335 3
  2489. Xa337 3
  2490. X    register char * lastslash, *tp;
  2491. X    if ((tp=tfnames[freefilename])==nil)
  2492. X        tp=tfnames[freefilename] = talloc(NCPPN);
  2493. Xd344 2
  2494. Xa345 2
  2495. X            while (fullpath<=lastslash) *tp++ = *fullpath++;
  2496. X    }
  2497. Xd347 4
  2498. Xa350 4
  2499. X    if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
  2500. X        /* copy path */
  2501. X        while (fullpath<=lastslash) *tp++ = *fullpath++;
  2502. X    }
  2503. Xd352 2
  2504. Xa353 2
  2505. X    while (*tp++ = *filename++);
  2506. X    return (mktemp(tfnames[freefilename++]));
  2507. Xd366 5
  2508. Xa370 5
  2509. X    r = sp;
  2510. X    while (*sp) {
  2511. X        if (*sp++ == c) r=sp;
  2512. X    }
  2513. X    return r;
  2514. Xa375 7
  2515. X#ifdef AMIGA
  2516. Xchar * fnamepart(char *sp)
  2517. X/*
  2518. X * Function: Finds the filename part of a path.
  2519. X */
  2520. X    {
  2521. X    char *p1;
  2522. Xa376 23
  2523. X    if (p1 = bindex(sp,':'))        /* volume: ? */
  2524. X        {
  2525. X        return bindex(p1, '/');
  2526. X        }
  2527. X    else
  2528. X        {
  2529. X        return bindex(sp,'/');
  2530. X        }
  2531. X
  2532. X    }
  2533. X#else
  2534. Xchar * fnamepart(char *sp)
  2535. X/*
  2536. X * Function: Finds the filename part of a path.
  2537. X */
  2538. X    {
  2539. X    return bindex(sp, '/');
  2540. X    }
  2541. X#endif
  2542. X
  2543. X
  2544. X
  2545. X
  2546. Xd380 1
  2547. Xa380 1
  2548. X    register int i;
  2549. Xd382 2
  2550. Xa383 2
  2551. X    Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
  2552. X    StrictLocks=STRICT_LOCKING;
  2553. Xd385 14
  2554. Xa398 14
  2555. X    /* guess the comment leader from the suffix*/
  2556. X    Suffix=bindex(workfilename, '.');
  2557. X    if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
  2558. X    for (i=0;;i++) {
  2559. X        if (comtable[i].suffix==nil) {
  2560. X            Comment=comtable[i].comlead; /*default*/
  2561. X            break;
  2562. X        } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
  2563. X            Comment=comtable[i].comlead; /*default*/
  2564. X            break;
  2565. X        }
  2566. X    }
  2567. X    Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
  2568. X}
  2569. Xd410 2
  2570. Xa411 2
  2571. X    register char * * next, * match;
  2572. X    register int count;
  2573. Xd413 10
  2574. Xa422 10
  2575. X    for (next = argv, count = argc; count>0; next++,count--) {
  2576. X        if ((*next != nil) && strcmp(fnamepart(*next),fname)==0) {
  2577. X            /* fnamepart finds the beginning of the file name stem */
  2578. X            match= *next;
  2579. X            *next=nil;
  2580. X            return match;
  2581. X        }
  2582. X    }
  2583. X    return fname;
  2584. X}
  2585. Xd450 4
  2586. Xa453 4
  2587. X    register char * sp, * tp;
  2588. X    char * lastsep, * purefname, * pureRCSname;
  2589. X    int opened, returncode;
  2590. X    char * RCS1;
  2591. Xd456 1
  2592. Xa456 1
  2593. X    if (*argv == nil) return 0; /* already paired filename */
  2594. Xd462 1
  2595. Xa462 1
  2596. X    InitCleanup();
  2597. Xd464 38
  2598. Xa501 38
  2599. X    /* first check suffix to see whether it is an RCS file or not */
  2600. X    purefname=fnamepart(*argv); /* skip path */
  2601. X    lastsep=rindex(purefname, RCSSEP);
  2602. X    if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
  2603. X        /* RCS file name given*/
  2604. X        RCS1=(*argv); pureRCSname=purefname;
  2605. X        /* derive workfilename*/
  2606. X        sp = purefname; tp=tempfilename;
  2607. X        while (sp<lastsep) *tp++ = *sp++; *tp='\0';
  2608. X        /* try to find workfile name among arguments */
  2609. X        workfilename=findpairfile(argc-1,argv+1,tempfilename);
  2610. X        if (strlen(pureRCSname)>NCPFN) {
  2611. X            error("RCS file name %s too long",RCS1);
  2612. X            return 0;
  2613. X        }
  2614. X    } else {
  2615. X        /* working file given; now try to find RCS file */
  2616. X        workfilename= *argv;
  2617. X        /* derive RCS file name*/
  2618. X        sp=purefname; tp=tempfilename;
  2619. X        while (*tp++ = *sp++);
  2620. X        *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp='\0';
  2621. X        /* Try to find RCS file name among arguments*/
  2622. X        RCS1=findpairfile(argc-1,argv+1,tempfilename);
  2623. X        pureRCSname=fnamepart(RCS1);
  2624. X        if (strlen(pureRCSname)>NCPFN) {
  2625. X            error("working file name %s too long",workfilename);
  2626. X            return 0;
  2627. X        }
  2628. X    }
  2629. X    /* now we have a (tentative) RCS filename in RCS1 and workfilename  */
  2630. X    /* First, get status of workfilename */
  2631. X    haveworkstat=stat(workfilename, &workstat);
  2632. X#ifdef TODO
  2633. X    if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
  2634. X        diagnose("Directory %s ignored",workfilename);
  2635. X        return 0;
  2636. X    }
  2637. Xd503 20
  2638. Xa522 20
  2639. X    /* Second, try to find the right RCS file */
  2640. X    if (pureRCSname!=RCS1) {
  2641. X        /* a path for RCSfile is given; single RCS file to look for */
  2642. X        finptr=fopen(RCSfilename=RCS1, "r");
  2643. X        if (finptr!=NULL) {
  2644. X            returncode=1;
  2645. X        } else { /* could not open */
  2646. X            if (access(RCSfilename,0)==0) {
  2647. X                error("Can't open existing %s", RCSfilename);
  2648. X                return 0;
  2649. X            }
  2650. X            if (mustread) {
  2651. X                error("Can't find %s", RCSfilename);
  2652. X                return 0;
  2653. X            } else {
  2654. X                /* initialize if not mustread */
  2655. X                returncode = -1;
  2656. X            }
  2657. X        }
  2658. X    } else {
  2659. Xd538 1
  2660. Xa538 1
  2661. X        opened=(
  2662. Xd542 5
  2663. Xa546 5
  2664. X        if (opened) {
  2665. X            /* open succeeded */
  2666. X            returncode=1;
  2667. X        } else {
  2668. X            /* open failed; may be read protected */
  2669. Xd549 4
  2670. Xa552 4
  2671. X                error("Can't open existing %s",RCSfilename);
  2672. X                return 0;
  2673. X            }
  2674. X            if (mustread) {
  2675. Xd554 3
  2676. Xa556 3
  2677. X                return 0;
  2678. X            } else {
  2679. X                /* initialize new file. Put into ./RCS if possible, strip off suffix*/
  2680. Xd559 2
  2681. Xa560 1
  2682. X                if (stat(prefdir,&pdirstat)) {
  2683. Xd562 3
  2684. Xa564 1
  2685. X                } else {
  2686. Xd566 1
  2687. Xa566 1
  2688. X                    if (pdirstat.st_type > 0) {
  2689. Xd568 1
  2690. Xa568 1
  2691. X                    if ((pdirstat.st_mode & S_IFMT) != S_IFREG) {
  2692. Xd570 1
  2693. Xd572 3
  2694. Xa574 1
  2695. X                    } else {
  2696. Xd576 1
  2697. Xd578 4
  2698. Xa581 5
  2699. X                }
  2700. X                returncode= -1;
  2701. X            }
  2702. X        }
  2703. X    }
  2704. Xd583 7
  2705. Xa589 7
  2706. X    if (returncode == 1) { /* RCS file open */
  2707. X#ifdef TODO
  2708. X        haveRCSstat=fstat(fileno(finptr),&RCSstat);
  2709. X        if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
  2710. X            diagnose("Directory %s ignored",RCSfilename);
  2711. X            return 0;
  2712. X        }
  2713. Xd591 5
  2714. Xa595 5
  2715. X        Lexinit(); getadmin();
  2716. X    } else {  /* returncode == -1; RCS file nonexisting */
  2717. X        haveRCSstat = -1;
  2718. X        InitAdmin();
  2719. X    };
  2720. Xd597 5
  2721. Xa601 5
  2722. X    if (tostdout&&
  2723. X        !(RCS1==tempfilename||workfilename==tempfilename))
  2724. X        /*The last term determines whether a pair of        */
  2725. X        /* file names was given in the argument list        */
  2726. X        warn("Option -p is set; ignoring output file %s",workfilename);
  2727. Xd603 1
  2728. Xa603 1
  2729. X    return returncode;
  2730. Xd613 2
  2731. Xa614 2
  2732. X    static char namebuf[NCPPN];
  2733. X    static int  pathlength;
  2734. Xd616 2
  2735. Xa617 2
  2736. X    register char * realname, * lastpathchar;
  2737. X    register int  dotdotcounter, realpathlength;
  2738. Xd619 49
  2739. Xa667 49
  2740. X    if (*RCSfilename=='/') {
  2741. X        return(RCSfilename);
  2742. X    } else {
  2743. X        if (pathlength==0) { /*call curdir for the first time*/
  2744. X            if (getwd(pathbuf)==NULL)
  2745. X                faterror("Can't build current directory path");
  2746. X            pathlength=strlen(pathbuf);
  2747. X            if (!((pathlength==1) && (pathbuf[0]=='/'))) {
  2748. X                pathbuf[pathlength++]='/';
  2749. X                /* Check needed because some getwd implementations */
  2750. X                /* generate "/" for the root.                      */
  2751. X            }
  2752. X        }
  2753. X        /*the following must be redone since RCSfilename may change*/
  2754. X        /* find how many ../ to remvove from RCSfilename */
  2755. X        dotdotcounter =0;
  2756. X        realname = RCSfilename;
  2757. X        while( realname[0]=='.' &&
  2758. X              (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
  2759. X            if (realname[1]=='/') {
  2760. X                /* drop leading ./ */
  2761. X                realname += 2;
  2762. X            } else {
  2763. X                /* drop leading ../ and remember */
  2764. X                dotdotcounter++;
  2765. X                realname += 3;
  2766. X            }
  2767. X        }
  2768. X        /* now remove dotdotcounter trailing directories from pathbuf*/
  2769. X        lastpathchar=pathbuf + pathlength-1;
  2770. X        while (dotdotcounter>0 && lastpathchar>pathbuf) {
  2771. X            /* move pointer backwards over trailing directory */
  2772. X            lastpathchar--;
  2773. X            if (*lastpathchar=='/') {
  2774. X                dotdotcounter--;
  2775. X            }
  2776. X        }
  2777. X        if (dotdotcounter>0) {
  2778. X            error("Can't generate full path name for RCS file");
  2779. X            return RCSfilename;
  2780. X        } else {
  2781. X            /* build full path name */
  2782. X            realpathlength=lastpathchar-pathbuf+1;
  2783. X            VOID strncpy(namebuf,pathbuf,realpathlength);
  2784. X            VOID strcpy(&namebuf[realpathlength],realname);
  2785. X            return(namebuf);
  2786. X        }
  2787. X    }
  2788. X}
  2789. Xd677 5
  2790. Xa681 5
  2791. X    char pathname[NCPPN];
  2792. X    register char * tp, *sp, *lp;
  2793. X    lp = rindex(filename,'/');
  2794. X    if (lp==0) {
  2795. X        /* check current directory */
  2796. Xd683 1
  2797. Xa683 1
  2798. X        return true;
  2799. Xd685 6
  2800. Xa690 6
  2801. X        if (access(".",2)==0)
  2802. X            return true;
  2803. X        else {
  2804. X            error("Current directory not writable");
  2805. X            return false;
  2806. X        }
  2807. Xd692 12
  2808. Xa703 12
  2809. X    }
  2810. X    /* copy path */
  2811. X    sp=filename;
  2812. X    tp=pathname;
  2813. X    do *tp++ = *sp++; while (sp<=lp);
  2814. X    *tp='\0';
  2815. X    if (access(pathname,2)==0)
  2816. X        return true;
  2817. X    else {
  2818. X        error("Directory %s not writable", pathname);
  2819. X        return false;
  2820. X    }
  2821. Xd718 3
  2822. Xa720 3
  2823. X             /* no harm done if file "to" does not exist            */
  2824. X    if (link(from,to)<0) return -1;
  2825. X    return(unlink(from));
  2826. Xd807 4
  2827. Xa810 4
  2828. X    FILE    *file;
  2829. X    struct  stat    d, dd;
  2830. X    char buf[2];    /* to NUL-terminate dir.d_name */
  2831. X    struct  direct  dir;
  2832. Xd812 3
  2833. Xa814 3
  2834. X    int rdev, rino;
  2835. X    int off;
  2836. X    register i,j;
  2837. Xd816 38
  2838. Xa853 38
  2839. X    name[off= 0] = '/';
  2840. X    name[1] = '\0';
  2841. X    buf[0] = '\0';
  2842. X    if (stat("/", &d)<0) return NULL;
  2843. X    rdev = d.st_dev;
  2844. X    rino = d.st_ino;
  2845. X    for (;;) {
  2846. X        if (stat(dot, &d)<0) return NULL;
  2847. X        if (d.st_ino==rino && d.st_dev==rdev) {
  2848. X            if (name[off] == '/') name[off] = '\0';
  2849. X            chdir(name); /*change back to current directory*/
  2850. X            return name;
  2851. X        }
  2852. X        if ((file = fopen(dotdot,"r")) == NULL) return NULL;
  2853. X        if (fstat(fileno(file), &dd)<0) goto fail;
  2854. X        chdir(dotdot);
  2855. X        if(d.st_dev == dd.st_dev) {
  2856. X            if(d.st_ino == dd.st_ino) {
  2857. X                if (name[off] == '/') name[off] = '\0';
  2858. X                chdir(name); /*change back to current directory*/
  2859. X                VOID fclose(file);
  2860. X                return name;
  2861. X            }
  2862. X            do {
  2863. X                if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
  2864. X                    goto fail;
  2865. X            } while (dir.d_ino != d.st_ino);
  2866. X        }
  2867. X        else do {
  2868. X            if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
  2869. X                goto fail;
  2870. X            }
  2871. X            if (dir.d_ino == 0)
  2872. X                dd.st_ino = d.st_ino + 1;
  2873. X            else if (stat(dir.d_name, &dd) < 0)
  2874. X                goto fail;
  2875. X        } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
  2876. X        VOID fclose(file);
  2877. Xd855 10
  2878. Xa864 10
  2879. X        /* concatenate file name */
  2880. X        i = -1;
  2881. X        while (dir.d_name[++i] != 0);
  2882. X        for(j=off+1; j>0; --j)
  2883. X            name[j+i+1] = name[j];
  2884. X        off=i+off+1;
  2885. X        name[i+1] = '/';
  2886. X        for(--i; i>=0; --i)
  2887. X            name[i+1] = dir.d_name[i];
  2888. X    } /* end for */
  2889. Xd867 1
  2890. Xa867 1
  2891. X    return NULL;
  2892. Xd883 4
  2893. Xa886 4
  2894. X    int result;
  2895. X    int initflag,tostdout;
  2896. X    quietflag=tostdout=initflag=false;
  2897. X    cmdid="pair";
  2898. Xd888 2
  2899. Xa889 2
  2900. X    while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
  2901. X        switch ((*argv)[1]) {
  2902. Xd891 10
  2903. Xa900 10
  2904. X        case 'p':       tostdout=true;
  2905. X                break;
  2906. X        case 'i':       initflag=true;
  2907. X                break;
  2908. X        case 'q':       quietflag=true;
  2909. X                break;
  2910. X        default:    error("unknown option: %s", *argv);
  2911. X                break;
  2912. X        }
  2913. X    }
  2914. Xd902 9
  2915. Xa910 9
  2916. X    do {
  2917. X        RCSfilename=workfilename=nil;
  2918. X        result=pairfilenames(argc,argv,!initflag,tostdout);
  2919. X        if (result!=0) {
  2920. X            diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
  2921. X            diagnose("Full RCS file name: %s", getfullRCSname());
  2922. X        }
  2923. X        switch (result) {
  2924. X            case 0: continue; /* already paired file */
  2925. Xd912 7
  2926. Xa918 7
  2927. X            case 1: if (initflag) {
  2928. X                    error("RCS file %s exists already",RCSfilename);
  2929. X                } else {
  2930. X                    diagnose("RCS file %s exists",RCSfilename);
  2931. X                }
  2932. X                VOID fclose(finptr);
  2933. X                break;
  2934. Xd920 3
  2935. Xa922 3
  2936. X            case -1:diagnose("RCS file does not exist");
  2937. X                break;
  2938. X        }
  2939. Xd924 1
  2940. Xa924 1
  2941. X    } while (++argv, --argc>=1);
  2942. X@
  2943. X
  2944. X
  2945. X4.8.2.5
  2946. Xlog
  2947. X@Removed some debugging code.
  2948. X@
  2949. Xtext
  2950. X@d6 1
  2951. Xa6 1
  2952. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.4 89/10/16 19:07:19 rsbx Exp $ Purdue CS";
  2953. Xa44 3
  2954. X * Revision 4.8.2.4  89/10/16  19:07:19  rsbx
  2955. X * Changed file path handling to deal with Amiga file path sematics.
  2956. X * 
  2957. Xd286 5
  2958. X@
  2959. X
  2960. X
  2961. X4.8.2.6
  2962. Xlog
  2963. X@Fix to fnamepart().
  2964. X@
  2965. Xtext
  2966. X@d6 1
  2967. Xa6 1
  2968. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.5 89/10/16 23:54:04 rsbx Exp $ Purdue CS";
  2969. Xa44 3
  2970. X * Revision 4.8.2.5  89/10/16  23:54:04  rsbx
  2971. X * Removed some debugging code.
  2972. X * 
  2973. Xd404 1
  2974. Xa404 1
  2975. X    if (p1 = strchr(sp,':'))        /* volume: ? */
  2976. Xa405 1
  2977. X        p1++;
  2978. X@
  2979. X
  2980. X
  2981. X4.8.2.7
  2982. Xlog
  2983. X@getfullRCSname() fixed up.
  2984. X@
  2985. Xtext
  2986. X@a152 3
  2987. X#ifdef AMIGA
  2988. Xchar * getfullRCSname();
  2989. X#endif
  2990. Xa654 1
  2991. X#ifndef AMIGA
  2992. Xa715 1
  2993. X#endif
  2994. Xd770 71
  2995. X@
  2996. X
  2997. X
  2998. X4.8.2.8
  2999. Xlog
  3000. X@mktemp() changed to use hex digits instead of decimal digits in temp
  3001. Xfile name.
  3002. X@
  3003. Xtext
  3004. X@d6 1
  3005. Xa6 1
  3006. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.7 89/10/17 18:38:55 rsbx Exp $ Purdue CS";
  3007. Xa44 3
  3008. X * Revision 4.8.2.7  89/10/17  18:38:55  rsbx
  3009. X * getfullRCSname() fixed up.
  3010. X * 
  3011. Xd912 5
  3012. Xa916 1
  3013. Xstatic char *hex = "0123456789abcdef";
  3014. Xa917 5
  3015. Xchar *mktemp(char *template)
  3016. X    {
  3017. X    char *cp;
  3018. X    unsigned long val;
  3019. X
  3020. Xa920 1
  3021. X        {
  3022. Xd922 3
  3023. Xa924 7
  3024. X            *cp = hex[val%16];
  3025. X            val /= 16;
  3026. X        }
  3027. X    else
  3028. X        {
  3029. X        if (*cp != '.')
  3030. X            {
  3031. Xa925 2
  3032. X            }
  3033. X        }
  3034. Xd927 1
  3035. Xa927 2
  3036. X    if (*++cp != 0)
  3037. X        {
  3038. Xd929 2
  3039. Xa930 4
  3040. X        while (access(template, 0) == 0)
  3041. X            {
  3042. X            if (*cp == 'Z')
  3043. X                {
  3044. Xd933 1
  3045. Xa933 1
  3046. X                }
  3047. Xa934 1
  3048. X            }
  3049. Xd936 1
  3050. Xa936 2
  3051. X    else
  3052. X        {
  3053. Xa937 1
  3054. X            {
  3055. Xd939 1
  3056. Xa939 2
  3057. X            }
  3058. X        }
  3059. Xd941 1
  3060. Xa941 1
  3061. X    }
  3062. X@
  3063. X
  3064. X
  3065. X4.8.2.9
  3066. Xlog
  3067. X@Previous changes to mktemp() had syntax errors.
  3068. X@
  3069. Xtext
  3070. X@d6 1
  3071. Xa6 1
  3072. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.8 89/10/30 13:44:29 rsbx Exp $ Purdue CS";
  3073. Xa44 4
  3074. X * Revision 4.8.2.8  89/10/30  13:44:29  rsbx
  3075. X * mktemp() changed to use hex digits instead of decimal digits in temp
  3076. X * file name.
  3077. X * 
  3078. Xd926 1
  3079. Xa926 2
  3080. X        if (*--cp == 'X')
  3081. X            {
  3082. Xd929 4
  3083. Xa932 2
  3084. X            }
  3085. X        else
  3086. Xd934 1
  3087. Xa934 4
  3088. X            if (*cp != '.')
  3089. X                {
  3090. X                break;
  3091. X                }
  3092. X@
  3093. X
  3094. X
  3095. X4.8.2.10
  3096. Xlog
  3097. X@Changes to make the delete bit to track the write bit. Made protection
  3098. Xbit manipulation less insane.
  3099. X@
  3100. Xtext
  3101. X@d6 1
  3102. Xa6 1
  3103. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.9 89/10/30 13:53:10 rsbx Exp $ Purdue CS";
  3104. Xa44 3
  3105. X * Revision 4.8.2.9  89/10/30  13:53:10  rsbx
  3106. X * Previous changes to mktemp() had syntax errors.
  3107. X * 
  3108. Xa641 1
  3109. X        haveRCSstat=stat(RCSfilename,&RCSstat);
  3110. Xd643 1
  3111. X@
  3112. X
  3113. X
  3114. X4.8.2.11
  3115. Xlog
  3116. X@Added support for RCS_link files to be used as a poor O/S's symbolic link.
  3117. X@
  3118. Xtext
  3119. X@d6 1
  3120. Xa6 1
  3121. X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.10 89/11/01 14:43:14 rsbx Exp $ Purdue CS";
  3122. Xa44 4
  3123. X * Revision 4.8.2.10  89/11/01  14:43:14  rsbx
  3124. X * Changes to make the delete bit to track the write bit. Made protection
  3125. X * bit manipulation less insane.
  3126. X * 
  3127. Xa176 3
  3128. X#ifdef LINK
  3129. Xchar sub3filename [NCPPN];     /* used for files path/RCS/file.sfx,v        */
  3130. X#endif /* LINK */
  3131. Xa521 3
  3132. X#ifdef LINK
  3133. X    char prefdir2[NCPPN];
  3134. X#endif /* LINK */
  3135. Xa592 13
  3136. X#ifdef LINK
  3137. X        FILE *symbolic_link_file = NULL;
  3138. X        sub3filename[0]='\0';
  3139. X        if ( access( "RCS_link", 0 ) == 0 )
  3140. X            symbolic_link_file = fopen( "RCS_link", "r" );
  3141. X        if ( symbolic_link_file ){
  3142. X            int sl;
  3143. X            fgets( sub3filename, NCPPN, symbolic_link_file );
  3144. X            fclose( symbolic_link_file );
  3145. X            sl = strlen(sub3filename);
  3146. X            sub3filename[sl?sl-1:0] = '\0';
  3147. X        }
  3148. X#endif /* LINK */
  3149. Xa601 5
  3150. X#ifdef LINK
  3151. X        prefdir2[0] = '\0';
  3152. X        if ( sub3filename[0] )
  3153. X            VOID strcpy(prefdir2,sub3filename); /* preferred directory for RCS file*/
  3154. X#endif /* LINK */
  3155. Xd603 1
  3156. Xa603 5
  3157. X        VOID strcat(sub1filename,RCS1);
  3158. X        VOID strcat(sub2filename,RCS1);
  3159. X#ifdef LINK
  3160. X        VOID strcat(sub3filename,RCS1);
  3161. X#endif /* LINK */
  3162. Xa604 1
  3163. X
  3164. Xd607 1
  3165. Xa607 6
  3166. X#ifdef LINK
  3167. X        ((finptr=fopen(RCSfilename=sub2filename, "r"))!=NULL) ||
  3168. X        (sub3filename[0] && ((finptr=fopen(RCSfilename=sub3filename, "r"))!=NULL)));
  3169. X#else
  3170. X        ((finptr=fopen(RCSfilename=sub2filename, "r"))!=NULL) );
  3171. X#endif /* LINK */
  3172. Xa614 4
  3173. X#ifdef LINK
  3174. X                (access(RCSfilename=sub2filename,0)==0) ||
  3175. X                (sub3filename[0] &&    (access(RCSfilename=sub3filename,0)==0))){
  3176. X#else
  3177. Xa615 1
  3178. X#endif /* LINK */
  3179. Xa619 6
  3180. X#ifdef LINK
  3181. X                if ( sub3filename[0] )
  3182. X                    error("Can't find %s, %s nor %s",sub1filename,sub2filename,sub3filename);
  3183. X                else
  3184. X                    error("Can't find %s nor %s",sub1filename,sub2filename);
  3185. X#else
  3186. Xa620 1
  3187. X#endif /* LINK */
  3188. Xa625 19
  3189. X#ifdef LINK
  3190. X#ifdef AMIGA
  3191. X                if (!stat(prefdir, &pdirstat) && (pdirstat.st_type > 0)) {
  3192. X#else
  3193. X                if (!stat(prefdir, &pdirstat) && ((pdirstat.st_mode & S_IFMT) != S_IFREG)) {
  3194. X#endif
  3195. X                    RCSfilename = sub1filename;
  3196. X                } else {
  3197. X#ifdef AMIGA
  3198. X                    if (!stat(prefdir2, &pdirstat) && (pdirstat.st_type > 0)) {
  3199. X#else
  3200. X                    if (!stat(prefdir2, &pdirstat) && ((pdirstat.st_mode & S_IFMT) != S_IFREG)) {
  3201. X#endif
  3202. X                        RCSfilename = sub3filename;
  3203. X                    } else {
  3204. X                        RCSfilename = sub2filename;
  3205. X                    }
  3206. X                }
  3207. X#else
  3208. Xa638 1
  3209. X#endif /* LINK */
  3210. X@
  3211. X
  3212. X
  3213. X4.8.1.1
  3214. Xlog
  3215. X@Start of cbmvax RCS source branch.
  3216. X@
  3217. Xtext
  3218. X@a45 3
  3219. X * checked in with -k by rsbx at 89.08.10.16.20.00.
  3220. X * 
  3221. X * Revision 4.8  89/05/01  15:09:41  narten
  3222. X@
  3223. SHAR_EOF
  3224. echo "End of archive 9 (of 14)"
  3225. # if you want to concatenate archives, remove anything after this line
  3226. exit
  3227.